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
Char8StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char16StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char32StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
WCharStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char8SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char16SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char32SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
WCharSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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