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::Char16StringSummaryProvider( 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("u"); 50 51 if (!StringPrinter::ReadStringAndDumpToStream< 52 StringPrinter::StringElementType::UTF16>(options)) { 53 stream.Printf("Summary Unavailable"); 54 return true; 55 } 56 57 return true; 58 } 59 60 bool lldb_private::formatters::Char32StringSummaryProvider( 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::UTF32>(options)) { 78 stream.Printf("Summary Unavailable"); 79 return true; 80 } 81 82 return true; 83 } 84 85 bool lldb_private::formatters::WCharStringSummaryProvider( 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 // Get a wchar_t basic type from the current type system 96 CompilerType wchar_compiler_type = 97 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 98 99 if (!wchar_compiler_type) 100 return false; 101 102 // Safe to pass nullptr for exe_scope here. 103 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 104 if (!size) 105 return false; 106 const uint32_t wchar_size = *size; 107 108 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 109 options.SetLocation(valobj_addr); 110 options.SetProcessSP(process_sp); 111 options.SetStream(&stream); 112 options.SetPrefixToken("L"); 113 114 switch (wchar_size) { 115 case 8: 116 return StringPrinter::ReadStringAndDumpToStream< 117 StringPrinter::StringElementType::UTF8>(options); 118 case 16: 119 return StringPrinter::ReadStringAndDumpToStream< 120 StringPrinter::StringElementType::UTF16>(options); 121 case 32: 122 return StringPrinter::ReadStringAndDumpToStream< 123 StringPrinter::StringElementType::UTF32>(options); 124 default: 125 stream.Printf("size for wchar_t is not valid"); 126 return true; 127 } 128 return true; 129 } 130 131 bool lldb_private::formatters::Char16SummaryProvider( 132 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 133 DataExtractor data; 134 Status error; 135 valobj.GetData(data, error); 136 137 if (error.Fail()) 138 return false; 139 140 std::string value; 141 valobj.GetValueAsCString(lldb::eFormatUnicode16, value); 142 if (!value.empty()) 143 stream.Printf("%s ", value.c_str()); 144 145 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 146 options.SetData(data); 147 options.SetStream(&stream); 148 options.SetPrefixToken("u"); 149 options.SetQuote('\''); 150 options.SetSourceSize(1); 151 options.SetBinaryZeroIsTerminator(false); 152 153 return StringPrinter::ReadBufferAndDumpToStream< 154 StringPrinter::StringElementType::UTF16>(options); 155 } 156 157 bool lldb_private::formatters::Char32SummaryProvider( 158 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 159 DataExtractor data; 160 Status error; 161 valobj.GetData(data, error); 162 163 if (error.Fail()) 164 return false; 165 166 std::string value; 167 valobj.GetValueAsCString(lldb::eFormatUnicode32, value); 168 if (!value.empty()) 169 stream.Printf("%s ", value.c_str()); 170 171 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 172 options.SetData(data); 173 options.SetStream(&stream); 174 options.SetPrefixToken("U"); 175 options.SetQuote('\''); 176 options.SetSourceSize(1); 177 options.SetBinaryZeroIsTerminator(false); 178 179 return StringPrinter::ReadBufferAndDumpToStream< 180 StringPrinter::StringElementType::UTF32>(options); 181 } 182 183 bool lldb_private::formatters::WCharSummaryProvider( 184 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { 185 DataExtractor data; 186 Status error; 187 valobj.GetData(data, error); 188 189 if (error.Fail()) 190 return false; 191 192 // Get a wchar_t basic type from the current type system 193 CompilerType wchar_compiler_type = 194 valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 195 196 if (!wchar_compiler_type) 197 return false; 198 199 // Safe to pass nullptr for exe_scope here. 200 llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 201 if (!size) 202 return false; 203 const uint32_t wchar_size = *size; 204 205 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); 206 options.SetData(data); 207 options.SetStream(&stream); 208 options.SetPrefixToken("L"); 209 options.SetQuote('\''); 210 options.SetSourceSize(1); 211 options.SetBinaryZeroIsTerminator(false); 212 213 switch (wchar_size) { 214 case 8: 215 return StringPrinter::ReadBufferAndDumpToStream< 216 StringPrinter::StringElementType::UTF8>(options); 217 case 16: 218 return StringPrinter::ReadBufferAndDumpToStream< 219 StringPrinter::StringElementType::UTF16>(options); 220 case 32: 221 return StringPrinter::ReadBufferAndDumpToStream< 222 StringPrinter::StringElementType::UTF32>(options); 223 default: 224 stream.Printf("size for wchar_t is not valid"); 225 return true; 226 } 227 return true; 228 } 229