1 //===-- CxxStringTypes.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CxxStringTypes.h"
11 
12 #include "llvm/Support/ConvertUTF.h"
13 
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/Symbol/ClangASTContext.h"
21 #include "lldb/Target/ProcessStructReader.h"
22 #include "lldb/Target/SectionLoadList.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 #include "lldb/Utility/DataBufferHeap.h"
26 #include "lldb/Utility/Endian.h"
27 #include "lldb/Utility/Status.h"
28 #include "lldb/Utility/Stream.h"
29 
30 #include <algorithm>
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 using namespace lldb_private::formatters;
35 
Char16StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)36 bool lldb_private::formatters::Char16StringSummaryProvider(
37     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
38   ProcessSP process_sp = valobj.GetProcessSP();
39   if (!process_sp)
40     return false;
41 
42   lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
43   if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
44     return false;
45 
46   StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
47   options.SetLocation(valobj_addr);
48   options.SetProcessSP(process_sp);
49   options.SetStream(&stream);
50   options.SetPrefixToken("u");
51 
52   if (!StringPrinter::ReadStringAndDumpToStream<
53           StringPrinter::StringElementType::UTF16>(options)) {
54     stream.Printf("Summary Unavailable");
55     return true;
56   }
57 
58   return true;
59 }
60 
Char32StringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)61 bool lldb_private::formatters::Char32StringSummaryProvider(
62     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
63   ProcessSP process_sp = valobj.GetProcessSP();
64   if (!process_sp)
65     return false;
66 
67   lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
68   if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
69     return false;
70 
71   StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
72   options.SetLocation(valobj_addr);
73   options.SetProcessSP(process_sp);
74   options.SetStream(&stream);
75   options.SetPrefixToken("U");
76 
77   if (!StringPrinter::ReadStringAndDumpToStream<
78           StringPrinter::StringElementType::UTF32>(options)) {
79     stream.Printf("Summary Unavailable");
80     return true;
81   }
82 
83   return true;
84 }
85 
WCharStringSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)86 bool lldb_private::formatters::WCharStringSummaryProvider(
87     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
88   ProcessSP process_sp = valobj.GetProcessSP();
89   if (!process_sp)
90     return false;
91 
92   lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
93   if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
94     return false;
95 
96   // Get a wchar_t basic type from the current type system
97   CompilerType wchar_compiler_type =
98       valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
99 
100   if (!wchar_compiler_type)
101     return false;
102 
103   // Safe to pass nullptr for exe_scope here.
104   llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
105   if (!size)
106     return false;
107   const uint32_t wchar_size = *size;
108 
109   StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
110   options.SetLocation(valobj_addr);
111   options.SetProcessSP(process_sp);
112   options.SetStream(&stream);
113   options.SetPrefixToken("L");
114 
115   switch (wchar_size) {
116   case 8:
117     return StringPrinter::ReadStringAndDumpToStream<
118         StringPrinter::StringElementType::UTF8>(options);
119   case 16:
120     return StringPrinter::ReadStringAndDumpToStream<
121         StringPrinter::StringElementType::UTF16>(options);
122   case 32:
123     return StringPrinter::ReadStringAndDumpToStream<
124         StringPrinter::StringElementType::UTF32>(options);
125   default:
126     stream.Printf("size for wchar_t is not valid");
127     return true;
128   }
129   return true;
130 }
131 
Char16SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)132 bool lldb_private::formatters::Char16SummaryProvider(
133     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
134   DataExtractor data;
135   Status error;
136   valobj.GetData(data, error);
137 
138   if (error.Fail())
139     return false;
140 
141   std::string value;
142   valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
143   if (!value.empty())
144     stream.Printf("%s ", value.c_str());
145 
146   StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
147   options.SetData(data);
148   options.SetStream(&stream);
149   options.SetPrefixToken("u");
150   options.SetQuote('\'');
151   options.SetSourceSize(1);
152   options.SetBinaryZeroIsTerminator(false);
153 
154   return StringPrinter::ReadBufferAndDumpToStream<
155       StringPrinter::StringElementType::UTF16>(options);
156 }
157 
Char32SummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)158 bool lldb_private::formatters::Char32SummaryProvider(
159     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
160   DataExtractor data;
161   Status error;
162   valobj.GetData(data, error);
163 
164   if (error.Fail())
165     return false;
166 
167   std::string value;
168   valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
169   if (!value.empty())
170     stream.Printf("%s ", value.c_str());
171 
172   StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
173   options.SetData(data);
174   options.SetStream(&stream);
175   options.SetPrefixToken("U");
176   options.SetQuote('\'');
177   options.SetSourceSize(1);
178   options.SetBinaryZeroIsTerminator(false);
179 
180   return StringPrinter::ReadBufferAndDumpToStream<
181       StringPrinter::StringElementType::UTF32>(options);
182 }
183 
WCharSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions &)184 bool lldb_private::formatters::WCharSummaryProvider(
185     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
186   DataExtractor data;
187   Status error;
188   valobj.GetData(data, error);
189 
190   if (error.Fail())
191     return false;
192 
193   // Get a wchar_t basic type from the current type system
194   CompilerType wchar_compiler_type =
195       valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
196 
197   if (!wchar_compiler_type)
198     return false;
199 
200     // Safe to pass nullptr for exe_scope here.
201   llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
202   if (!size)
203     return false;
204   const uint32_t wchar_size = *size;
205 
206   StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
207   options.SetData(data);
208   options.SetStream(&stream);
209   options.SetPrefixToken("L");
210   options.SetQuote('\'');
211   options.SetSourceSize(1);
212   options.SetBinaryZeroIsTerminator(false);
213 
214   switch (wchar_size) {
215   case 8:
216     return StringPrinter::ReadBufferAndDumpToStream<
217         StringPrinter::StringElementType::UTF8>(options);
218   case 16:
219     return StringPrinter::ReadBufferAndDumpToStream<
220         StringPrinter::StringElementType::UTF16>(options);
221   case 32:
222     return StringPrinter::ReadBufferAndDumpToStream<
223         StringPrinter::StringElementType::UTF32>(options);
224   default:
225     stream.Printf("size for wchar_t is not valid");
226     return true;
227   }
228   return true;
229 }
230