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>
getElementTraits(StringElementType ElemType)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>
CharStringSummaryProvider(ValueObject & valobj,Stream & stream)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>
CharSummaryProvider(ValueObject & valobj,Stream & stream)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
Char8StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)98 bool lldb_private::formatters::Char8StringSummaryProvider(
99 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
100 return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream);
101 }
102
Char16StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)103 bool lldb_private::formatters::Char16StringSummaryProvider(
104 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
105 return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream);
106 }
107
Char32StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)108 bool lldb_private::formatters::Char32StringSummaryProvider(
109 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
110 return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream);
111 }
112
WCharStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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
Char8SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)155 bool lldb_private::formatters::Char8SummaryProvider(
156 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
157 return CharSummaryProvider<StringElementType::UTF8>(valobj, stream);
158 }
159
Char16SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)160 bool lldb_private::formatters::Char16SummaryProvider(
161 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
162 return CharSummaryProvider<StringElementType::UTF16>(valobj, stream);
163 }
164
Char32SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)165 bool lldb_private::formatters::Char32SummaryProvider(
166 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
167 return CharSummaryProvider<StringElementType::UTF32>(valobj, stream);
168 }
169
WCharSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)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