blob: 6bf1d56a8ca92271b971a4c4eedb5d531abd3eea [file] [log] [blame]
Enrico Granataf5196282012-09-04 18:48:21 +00001//===-- CXXFormatterFunctions.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
Enrico Granata5548cb52013-01-28 23:47:25 +000010#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granataca6c8ee2014-10-30 01:45:39 +000011#include "lldb/DataFormatters/StringPrinter.h"
Enrico Granata34042212014-11-18 22:54:45 +000012#include "lldb/DataFormatters/TypeSummary.h"
Enrico Granataf5196282012-09-04 18:48:21 +000013
Dmitri Gribenko024aa852013-01-30 15:05:59 +000014#include "llvm/Support/ConvertUTF.h"
Enrico Granataf5196282012-09-04 18:48:21 +000015
Enrico Granatab2698cd2012-09-13 18:27:09 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/Error.h"
Enrico Granataf5196282012-09-04 18:48:21 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/ValueObject.h"
Enrico Granatab2698cd2012-09-13 18:27:09 +000020#include "lldb/Core/ValueObjectConstResult.h"
21#include "lldb/Host/Endian.h"
Enrico Granatab5887262012-10-29 21:18:03 +000022#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataff0f23d2014-12-10 02:00:45 +000023#include "lldb/Target/SectionLoadList.h"
Enrico Granataf5196282012-09-04 18:48:21 +000024#include "lldb/Target/Target.h"
Enrico Granataba8eb122014-07-30 21:07:50 +000025#include "lldb/Target/Thread.h"
Enrico Granataf5196282012-09-04 18:48:21 +000026
Enrico Granata76b08d52014-10-29 23:08:02 +000027#include "lldb/Utility/ProcessStructReader.h"
28
Enrico Granatad83bfce2013-04-02 21:25:34 +000029#include <algorithm>
Vince Harron8b335672015-05-12 01:10:56 +000030
Shawn Best8da0bf32014-11-08 01:41:49 +000031#if __ANDROID_NDK__
32#include <sys/types.h>
33#endif
Enrico Granatad83bfce2013-04-02 21:25:34 +000034
Vince Harron8b335672015-05-12 01:10:56 +000035#include "lldb/Host/Time.h"
36
Enrico Granataf5196282012-09-04 18:48:21 +000037using namespace lldb;
38using namespace lldb_private;
39using namespace lldb_private::formatters;
40
Enrico Granataba8eb122014-07-30 21:07:50 +000041StackFrame*
42lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
43{
44 StackFrame* frame = exe_ctx.GetFramePtr();
45 if (frame)
46 return frame;
47
48 Process* process = exe_ctx.GetProcessPtr();
49 if (!process)
50 return nullptr;
51
52 ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
53 if (thread_sp)
54 return thread_sp->GetSelectedFrame().get();
55 return nullptr;
56}
57
Enrico Granataf5196282012-09-04 18:48:21 +000058bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000059lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
60 const char* target_type,
61 const char* selector,
62 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000063{
64 if (!target_type || !*target_type)
65 return false;
66 if (!selector || !*selector)
67 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000068 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000069 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000070 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
71 lldb::ValueObjectSP result_sp;
72 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +000073 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf5196282012-09-04 18:48:21 +000074 if (!target || !stack_frame)
75 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000076
Jim Ingham35e1bda2012-10-16 21:41:58 +000077 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000078 options.SetCoerceToId(false);
79 options.SetUnwindOnError(true);
80 options.SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000081
Enrico Granataf5196282012-09-04 18:48:21 +000082 target->EvaluateExpression(expr.GetData(),
83 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000084 result_sp,
85 options);
Enrico Granataf5196282012-09-04 18:48:21 +000086 if (!result_sp)
87 return false;
88 value = result_sp->GetValueAsUnsigned(0);
89 return true;
90}
91
Enrico Granataf615b802013-02-15 23:38:37 +000092bool
93lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
94 const char* target_type,
95 const char* selector,
96 Stream &stream)
97{
98 if (!target_type || !*target_type)
99 return false;
100 if (!selector || !*selector)
101 return false;
102 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +0000103 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +0000104 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
105 lldb::ValueObjectSP result_sp;
106 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000107 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf615b802013-02-15 23:38:37 +0000108 if (!target || !stack_frame)
109 return false;
110
111 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000112 options.SetCoerceToId(false);
113 options.SetUnwindOnError(true);
114 options.SetKeepInMemory(true);
115 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataf615b802013-02-15 23:38:37 +0000116
117 target->EvaluateExpression(expr.GetData(),
118 stack_frame,
119 result_sp,
120 options);
121 if (!result_sp)
122 return false;
123 stream.Printf("%s",result_sp->GetSummaryAsCString());
124 return true;
125}
126
Enrico Granatab2698cd2012-09-13 18:27:09 +0000127lldb::ValueObjectSP
128lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
129 const char* return_type,
130 const char* selector,
131 uint64_t index)
132{
133 lldb::ValueObjectSP valobj_sp;
134 if (!return_type || !*return_type)
135 return valobj_sp;
136 if (!selector || !*selector)
137 return valobj_sp;
138 StreamString expr_path_stream;
139 valobj.GetExpressionPath(expr_path_stream, false);
140 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000141 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000142 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
143 lldb::ValueObjectSP result_sp;
144 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000145 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000146 if (!target || !stack_frame)
147 return valobj_sp;
148
Jim Ingham35e1bda2012-10-16 21:41:58 +0000149 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000150 options.SetCoerceToId(false);
151 options.SetUnwindOnError(true);
152 options.SetKeepInMemory(true);
153 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000154
155 target->EvaluateExpression(expr.GetData(),
156 stack_frame,
157 valobj_sp,
158 options);
159 return valobj_sp;
160}
161
162lldb::ValueObjectSP
163lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
164 const char* return_type,
165 const char* selector,
166 const char* key)
167{
168 lldb::ValueObjectSP valobj_sp;
169 if (!return_type || !*return_type)
170 return valobj_sp;
171 if (!selector || !*selector)
172 return valobj_sp;
173 if (!key || !*key)
174 return valobj_sp;
175 StreamString expr_path_stream;
176 valobj.GetExpressionPath(expr_path_stream, false);
177 StreamString expr;
178 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
179 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
180 lldb::ValueObjectSP result_sp;
181 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000182 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000183 if (!target || !stack_frame)
184 return valobj_sp;
185
Jim Ingham35e1bda2012-10-16 21:41:58 +0000186 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000187 options.SetCoerceToId(false);
188 options.SetUnwindOnError(true);
189 options.SetKeepInMemory(true);
190 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000191
192 target->EvaluateExpression(expr.GetData(),
193 stack_frame,
194 valobj_sp,
195 options);
196 return valobj_sp;
197}
198
Enrico Granataf68df122013-01-10 22:08:35 +0000199bool
Enrico Granataff0f23d2014-12-10 02:00:45 +0000200lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
201{
202 std::string destination;
203 StreamString sstr;
204 AddressType func_ptr_address_type = eAddressTypeInvalid;
205 addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
206 if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
207 {
208 switch (func_ptr_address_type)
209 {
210 case eAddressTypeInvalid:
211 case eAddressTypeFile:
212 case eAddressTypeHost:
213 break;
214
215 case eAddressTypeLoad:
216 {
217 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
218
219 Address so_addr;
220 Target *target = exe_ctx.GetTargetPtr();
221 if (target && target->GetSectionLoadList().IsEmpty() == false)
222 {
223 if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
224 {
225 so_addr.Dump (&sstr,
226 exe_ctx.GetBestExecutionContextScope(),
227 Address::DumpStyleResolvedDescription,
228 Address::DumpStyleSectionNameOffset);
229 }
230 }
231 }
232 break;
233 }
234 }
235 if (sstr.GetSize() > 0)
236 {
237 stream.Printf("(%s)", sstr.GetData());
238 return true;
239 }
240 else
241 return false;
242}
243
244bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000245lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000246{
247 ProcessSP process_sp = valobj.GetProcessSP();
248 if (!process_sp)
249 return false;
250
251 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
252
253 if (!valobj_addr)
254 return false;
255
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000256 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000257 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000258 options.SetProcessSP(process_sp);
259 options.SetStream(&stream);
260 options.SetPrefixToken('u');
261
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000262 if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000263 {
264 stream.Printf("Summary Unavailable");
265 return true;
266 }
267
268 return true;
269}
270
271bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000272lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000273{
274 ProcessSP process_sp = valobj.GetProcessSP();
275 if (!process_sp)
276 return false;
277
278 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
279
280 if (!valobj_addr)
281 return false;
282
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000283 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000284 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000285 options.SetProcessSP(process_sp);
286 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000287 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000288
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000289 if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000290 {
291 stream.Printf("Summary Unavailable");
292 return true;
293 }
294
295 return true;
296}
297
298bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000299lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000300{
Enrico Granata38352042013-01-11 02:44:00 +0000301 ProcessSP process_sp = valobj.GetProcessSP();
302 if (!process_sp)
303 return false;
304
Enrico Granata3309d882013-01-12 01:00:22 +0000305 lldb::addr_t data_addr = 0;
306
307 if (valobj.IsPointerType())
308 data_addr = valobj.GetValueAsUnsigned(0);
309 else if (valobj.IsArrayType())
310 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000311
Enrico Granata3309d882013-01-12 01:00:22 +0000312 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000313 return false;
314
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000315 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
Greg Clayton57ee3062013-07-11 22:46:58 +0000316
Enrico Granata38352042013-01-11 02:44:00 +0000317 if (!ast)
318 return false;
319
Greg Clayton57ee3062013-07-11 22:46:58 +0000320 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
Greg Clayton526ae042015-02-12 00:34:25 +0000321 const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
Enrico Granata38352042013-01-11 02:44:00 +0000322
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000323 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000324 options.SetLocation(data_addr);
325 options.SetProcessSP(process_sp);
326 options.SetStream(&stream);
327 options.SetPrefixToken('L');
328
Enrico Granata38352042013-01-11 02:44:00 +0000329 switch (wchar_size)
330 {
331 case 8:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000332 return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000333 case 16:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000334 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000335 case 32:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000336 return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000337 default:
338 stream.Printf("size for wchar_t is not valid");
339 return true;
340 }
341 return true;
342}
343
344bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000345lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000346{
347 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000348 Error error;
349 valobj.GetData(data, error);
350
351 if (error.Fail())
352 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000353
354 std::string value;
355 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
356 if (!value.empty())
357 stream.Printf("%s ", value.c_str());
358
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000359 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000360 options.SetData(data);
361 options.SetStream(&stream);
362 options.SetPrefixToken('u');
363 options.SetQuote('\'');
364 options.SetSourceSize(1);
Enrico Granata8a1cedd2015-07-17 20:54:52 +0000365 options.SetBinaryZeroIsTerminator(false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000366
367 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000368}
369
370bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000371lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000372{
373 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000374 Error error;
375 valobj.GetData(data, error);
376
377 if (error.Fail())
378 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000379
380 std::string value;
381 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
382 if (!value.empty())
383 stream.Printf("%s ", value.c_str());
384
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000385 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000386 options.SetData(data);
387 options.SetStream(&stream);
388 options.SetPrefixToken('U');
389 options.SetQuote('\'');
390 options.SetSourceSize(1);
Enrico Granata8a1cedd2015-07-17 20:54:52 +0000391 options.SetBinaryZeroIsTerminator(false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000392
393 return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000394}
395
396bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000397lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000398{
399 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000400 Error error;
401 valobj.GetData(data, error);
402
403 if (error.Fail())
404 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000405
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000406 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000407 options.SetData(data);
408 options.SetStream(&stream);
409 options.SetPrefixToken('L');
410 options.SetQuote('\'');
411 options.SetSourceSize(1);
Enrico Granata8a1cedd2015-07-17 20:54:52 +0000412 options.SetBinaryZeroIsTerminator(false);
Enrico Granata93d59662013-01-14 23:53:26 +0000413
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000414 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granataf68df122013-01-10 22:08:35 +0000415}
416
Enrico Granataa3962a72013-05-15 00:47:46 +0000417// the field layout in a libc++ string (cap, side, data or data, size, cap)
418enum LibcxxStringLayoutMode
419{
420 eLibcxxStringLayoutModeCSD = 0,
421 eLibcxxStringLayoutModeDSC = 1,
422 eLibcxxStringLayoutModeInvalid = 0xffff
423};
424
425// this function abstracts away the layout and mode details of a libc++ string
426// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000427static bool
428ExtractLibcxxStringInfo (ValueObject& valobj,
429 ValueObjectSP &location_sp,
430 uint64_t& size)
431{
432 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
433 if (!D)
434 return false;
435
Enrico Granataa3962a72013-05-15 00:47:46 +0000436 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
437
438 // this child should exist
439 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000440 return false;
441
Enrico Granataa3962a72013-05-15 00:47:46 +0000442 ConstString g_data_name("__data_");
443 ConstString g_size_name("__size_");
444 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
445 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
446 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000447
Enrico Granataa3962a72013-05-15 00:47:46 +0000448 if (layout == eLibcxxStringLayoutModeDSC)
449 {
450 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
451 if (!size_mode)
452 return false;
453
454 if (size_mode->GetName() != g_size_name)
455 {
456 // we are hitting the padding structure, move along
457 size_mode = D->GetChildAtIndexPath({1,1,1});
458 if (!size_mode)
459 return false;
460 }
461
462 size_mode_value = (size_mode->GetValueAsUnsigned(0));
463 short_mode = ((size_mode_value & 0x80) == 0);
464 }
465 else
466 {
467 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
468 if (!size_mode)
469 return false;
470
471 size_mode_value = (size_mode->GetValueAsUnsigned(0));
472 short_mode = ((size_mode_value & 1) == 0);
473 }
474
475 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000476 {
477 ValueObjectSP s(D->GetChildAtIndex(1, true));
478 if (!s)
479 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000480 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
481 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000482 return (location_sp.get() != nullptr);
483 }
484 else
485 {
486 ValueObjectSP l(D->GetChildAtIndex(0, true));
487 if (!l)
488 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000489 // we can use the layout_decider object as the data pointer
490 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000491 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
492 if (!size_vo || !location_sp)
493 return false;
494 size = size_vo->GetValueAsUnsigned(0);
495 return true;
496 }
497}
498
499bool
Enrico Granata8101f572015-07-17 01:56:25 +0000500lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000501{
502 uint64_t size = 0;
503 ValueObjectSP location_sp((ValueObject*)nullptr);
504 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
505 return false;
506 if (size == 0)
507 {
508 stream.Printf("L\"\"");
509 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000510 }
Enrico Granata3309d882013-01-12 01:00:22 +0000511 if (!location_sp)
512 return false;
Enrico Granata8101f572015-07-17 01:56:25 +0000513
514 DataExtractor extractor;
515 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
516 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
517 location_sp->GetPointeeData(extractor, 0, size);
518
519 // std::wstring::size() is measured in 'characters', not bytes
520 auto wchar_t_size = valobj.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
521
522 ReadBufferAndDumpToStreamOptions options(valobj);
523 options.SetData(extractor);
524 options.SetStream(&stream);
525 options.SetPrefixToken('L');
526 options.SetQuote('"');
527 options.SetSourceSize(size);
528 options.SetBinaryZeroIsTerminator(false);
529
530 switch (wchar_t_size)
531 {
532 case 1:
533 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF8>(options);
534 break;
535
536 case 2:
537 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF16>(options);
538 break;
539
540 case 4:
541 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF32>(options);
542 break;
543
544 default:
545 stream.Printf("size for wchar_t is not valid");
546 return true;
547 }
548
549 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000550}
551
552bool
Enrico Granata34042212014-11-18 22:54:45 +0000553lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000554{
555 uint64_t size = 0;
556 ValueObjectSP location_sp((ValueObject*)nullptr);
Enrico Granata2206b482014-10-30 18:27:31 +0000557
Enrico Granata3309d882013-01-12 01:00:22 +0000558 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
559 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000560
Enrico Granata3309d882013-01-12 01:00:22 +0000561 if (size == 0)
562 {
563 stream.Printf("\"\"");
564 return true;
565 }
Enrico Granata2206b482014-10-30 18:27:31 +0000566
Enrico Granata3309d882013-01-12 01:00:22 +0000567 if (!location_sp)
568 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000569
570 DataExtractor extractor;
Enrico Granata34042212014-11-18 22:54:45 +0000571 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
572 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
Enrico Granata2206b482014-10-30 18:27:31 +0000573 location_sp->GetPointeeData(extractor, 0, size);
574
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000575 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granata8101f572015-07-17 01:56:25 +0000576 options.SetData(extractor);
Enrico Granata2206b482014-10-30 18:27:31 +0000577 options.SetStream(&stream);
578 options.SetPrefixToken(0);
579 options.SetQuote('"');
580 options.SetSourceSize(size);
Enrico Granatad07f7552015-07-17 01:03:59 +0000581 options.SetBinaryZeroIsTerminator(false);
Enrico Granata2206b482014-10-30 18:27:31 +0000582 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
583
584 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000585}
586
Enrico Granata55900862013-03-15 18:55:30 +0000587bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000588lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata55900862013-03-15 18:55:30 +0000589{
590 ProcessSP process_sp = valobj.GetProcessSP();
591 if (!process_sp)
592 return false;
593
594 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
595
596 if (!runtime)
597 return false;
598
Greg Clayton03da4cc2013-04-19 21:31:16 +0000599 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000600
601 if (!descriptor.get() || !descriptor->IsValid())
602 return false;
603
604 const char* class_name = descriptor->GetClassName().GetCString();
605
606 if (!class_name || !*class_name)
607 return false;
608
609 stream.Printf("%s",class_name);
610 return true;
611}
612
Enrico Granatac76b97b2013-04-26 00:59:02 +0000613class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
614{
615public:
616 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
617 SyntheticChildrenFrontEnd(*valobj_sp.get())
618 {
619 }
620
621 virtual size_t
622 CalculateNumChildren ()
623 {
624 return 0;
625 }
626
627 virtual lldb::ValueObjectSP
628 GetChildAtIndex (size_t idx)
629 {
630 return lldb::ValueObjectSP();
631 }
632
633 virtual bool
634 Update()
635 {
636 return false;
637 }
638
639 virtual bool
640 MightHaveChildren ()
641 {
642 return false;
643 }
644
645 virtual size_t
646 GetIndexOfChildWithName (const ConstString &name)
647 {
648 return UINT32_MAX;
649 }
650
651 virtual
652 ~ObjCClassSyntheticChildrenFrontEnd ()
653 {
654 }
655};
656
657SyntheticChildrenFrontEnd*
658lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
659{
660 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
661}
662
Enrico Granataf5196282012-09-04 18:48:21 +0000663template<bool needs_at>
664bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000665lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf5196282012-09-04 18:48:21 +0000666{
667 ProcessSP process_sp = valobj.GetProcessSP();
668 if (!process_sp)
669 return false;
670
671 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
672
673 if (!runtime)
674 return false;
675
676 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
677
678 if (!descriptor.get() || !descriptor->IsValid())
679 return false;
680
681 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
682 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
683
684 if (!valobj_addr)
685 return false;
686
687 uint64_t value = 0;
688
689 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000690
691 if (!class_name || !*class_name)
692 return false;
693
Enrico Granataf5196282012-09-04 18:48:21 +0000694 if (!strcmp(class_name,"NSConcreteData") ||
695 !strcmp(class_name,"NSConcreteMutableData") ||
696 !strcmp(class_name,"__NSCFData"))
697 {
698 uint32_t offset = (is_64bit ? 16 : 8);
699 Error error;
700 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
701 if (error.Fail())
702 return false;
703 }
704 else
705 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000706 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000707 return false;
708 }
709
Daniel Malead01b2952012-11-29 21:49:15 +0000710 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000711 (needs_at ? "@\"" : ""),
712 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000713 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000714 (needs_at ? "\"" : ""));
715
716 return true;
717}
718
Enrico Granataf5196282012-09-04 18:48:21 +0000719bool
Jason Molenda705b1802014-06-13 02:37:02 +0000720lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
721{
722 if (!descriptor)
723 return false;
724 uint64_t len_bits = 0, data_bits = 0;
725 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
726 return false;
727
728 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
729 static const int g_SixbitMaxLen = 9;
730 static const int g_fiveBitMaxLen = 11;
731
732 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
733
734 if (len_bits > g_fiveBitMaxLen)
735 return false;
736
737 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
738 // this works under a few assumptions:
739 // little endian architecture
740 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
741 if (len_bits <= g_MaxNonBitmaskedLen)
742 {
743 stream.Printf("@\"%s\"",(const char*)&data_bits);
744 return true;
745 }
746
747 // if the data is bitmasked, we need to actually process the bytes
748 uint8_t bitmask = 0;
749 uint8_t shift_offset = 0;
750
751 if (len_bits <= g_SixbitMaxLen)
752 {
753 bitmask = 0x03f;
754 shift_offset = 6;
755 }
756 else
757 {
758 bitmask = 0x01f;
759 shift_offset = 5;
760 }
761
762 std::vector<uint8_t> bytes;
763 bytes.resize(len_bits);
764 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
765 {
766 uint8_t packed = data_bits & bitmask;
767 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
768 }
769
770 stream.Printf("@\"%s\"",&bytes[0]);
771 return true;
772}
773
Enrico Granata76b08d52014-10-29 23:08:02 +0000774static ClangASTType
775GetNSPathStore2Type (Target &target)
776{
777 static ConstString g_type_name("__lldb_autogen_nspathstore2");
778
779 ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
780
781 if (!ast_ctx)
782 return ClangASTType();
783
784 ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
785 ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
786
787 return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
788 {"isa",voidstar},
789 {"lengthAndRef",uint32},
790 {"buffer",voidstar}
791 });
792}
793
Jason Molenda705b1802014-06-13 02:37:02 +0000794bool
Enrico Granata34042212014-11-18 22:54:45 +0000795lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granataf5196282012-09-04 18:48:21 +0000796{
797 ProcessSP process_sp = valobj.GetProcessSP();
798 if (!process_sp)
799 return false;
800
801 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
802
803 if (!runtime)
804 return false;
805
806 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
807
808 if (!descriptor.get() || !descriptor->IsValid())
809 return false;
810
811 uint32_t ptr_size = process_sp->GetAddressByteSize();
812
813 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
814
815 if (!valobj_addr)
816 return false;
817
818 const char* class_name = descriptor->GetClassName().GetCString();
819
Enrico Granata60b81df2012-09-29 00:45:53 +0000820 if (!class_name || !*class_name)
821 return false;
822
Jason Molenda705b1802014-06-13 02:37:02 +0000823 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
824 // for a tagged pointer, the descriptor has everything we need
825 if (is_tagged_ptr)
826 return NSTaggedString_SummaryProvider(descriptor, stream);
827
828 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +0000829 uint64_t info_bits_location = valobj_addr + ptr_size;
830 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
831 info_bits_location += 3;
832
Enrico Granata87f00b42013-02-21 20:31:18 +0000833 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000834
835 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
836 if (error.Fail())
837 return false;
838
839 bool is_mutable = (info_bits & 1) == 1;
840 bool is_inline = (info_bits & 0x60) == 0;
841 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
842 bool is_unicode = (info_bits & 0x10) == 0x10;
Enrico Granataf2198852015-07-17 18:22:51 +0000843 bool is_path_store = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000844 bool has_null = (info_bits & 8) == 8;
845
846 size_t explicit_length = 0;
Enrico Granataf2198852015-07-17 18:22:51 +0000847 if (!has_null && has_explicit_length && !is_path_store)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000848 {
849 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000850 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000851 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
852 else if (is_inline)
853 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000854 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000855 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
856 else
857 explicit_length_offset = 0;
858
859 if (explicit_length_offset)
860 {
861 explicit_length_offset = valobj_addr + explicit_length_offset;
862 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
863 }
864 }
865
Enrico Granataf5196282012-09-04 18:48:21 +0000866 if (strcmp(class_name,"NSString") &&
867 strcmp(class_name,"CFStringRef") &&
868 strcmp(class_name,"CFMutableStringRef") &&
869 strcmp(class_name,"__NSCFConstantString") &&
870 strcmp(class_name,"__NSCFString") &&
871 strcmp(class_name,"NSCFConstantString") &&
872 strcmp(class_name,"NSCFString") &&
873 strcmp(class_name,"NSPathStore2"))
874 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000875 // not one of us - but tell me class name
876 stream.Printf("class name = %s",class_name);
877 return true;
Enrico Granataf5196282012-09-04 18:48:21 +0000878 }
879
880 if (is_mutable)
881 {
882 uint64_t location = 2 * ptr_size + valobj_addr;
883 location = process_sp->ReadPointerFromMemory(location, error);
884 if (error.Fail())
885 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000886 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +0000887 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000888 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000889 options.SetLocation(location);
890 options.SetProcessSP(process_sp);
891 options.SetStream(&stream);
892 options.SetPrefixToken('@');
893 options.SetQuote('"');
894 options.SetSourceSize(explicit_length);
895 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000896 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataf2198852015-07-17 18:22:51 +0000897 options.SetBinaryZeroIsTerminator(false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000898 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata56768392013-04-23 20:05:05 +0000899 }
Enrico Granataf5196282012-09-04 18:48:21 +0000900 else
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000901 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000902 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000903 options.SetLocation(location+1);
904 options.SetProcessSP(process_sp);
905 options.SetStream(&stream);
906 options.SetPrefixToken('@');
907 options.SetSourceSize(explicit_length);
908 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000909 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataf2198852015-07-17 18:22:51 +0000910 options.SetBinaryZeroIsTerminator(false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000911 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
912 }
Enrico Granataf5196282012-09-04 18:48:21 +0000913 }
Enrico Granataf2198852015-07-17 18:22:51 +0000914 else if (is_inline && has_explicit_length && !is_unicode && !is_path_store && !is_mutable)
Enrico Granataf5196282012-09-04 18:48:21 +0000915 {
916 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granata91443ed2015-07-17 22:39:35 +0000917
918 ReadStringAndDumpToStreamOptions options(valobj);
919 options.SetLocation(location);
920 options.SetProcessSP(process_sp);
921 options.SetStream(&stream);
922 options.SetPrefixToken('@');
923 options.SetQuote('"');
924 options.SetSourceSize(explicit_length);
925 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
926 return ReadStringAndDumpToStream<StringElementType::ASCII> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000927 }
928 else if (is_unicode)
929 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000930 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000931 if (is_inline)
932 {
933 if (!has_explicit_length)
934 {
935 stream.Printf("found new combo");
936 return true;
937 }
938 else
939 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +0000940 }
Enrico Granataf5196282012-09-04 18:48:21 +0000941 else
942 {
943 location = process_sp->ReadPointerFromMemory(location, error);
944 if (error.Fail())
945 return false;
946 }
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000947 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000948 options.SetLocation(location);
949 options.SetProcessSP(process_sp);
950 options.SetStream(&stream);
951 options.SetPrefixToken('@');
952 options.SetQuote('"');
953 options.SetSourceSize(explicit_length);
954 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000955 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataf2198852015-07-17 18:22:51 +0000956 options.SetBinaryZeroIsTerminator(has_explicit_length == false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000957 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000958 }
Enrico Granataf2198852015-07-17 18:22:51 +0000959 else if (is_path_store)
Enrico Granataf5196282012-09-04 18:48:21 +0000960 {
Enrico Granata76b08d52014-10-29 23:08:02 +0000961 ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
962 explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
963 lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
964
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000965 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000966 options.SetLocation(location);
967 options.SetProcessSP(process_sp);
968 options.SetStream(&stream);
969 options.SetPrefixToken('@');
970 options.SetQuote('"');
971 options.SetSourceSize(explicit_length);
972 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000973 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataf2198852015-07-17 18:22:51 +0000974 options.SetBinaryZeroIsTerminator(has_explicit_length == false);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000975 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000976 }
977 else if (is_inline)
978 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000979 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000980 if (!has_explicit_length)
Enrico Granata01dcaa32015-07-17 19:06:39 +0000981 {
982 // in this kind of string, the byte before the string content is a length byte
983 // so let's try and use it to handle the embedded NUL case
984 Error error;
985 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
986 if (error.Fail() || explicit_length == 0)
987 has_explicit_length = false;
988 else
989 has_explicit_length = true;
Enrico Granataf5196282012-09-04 18:48:21 +0000990 location++;
Enrico Granata01dcaa32015-07-17 19:06:39 +0000991 }
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000992 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000993 options.SetLocation(location);
994 options.SetProcessSP(process_sp);
995 options.SetStream(&stream);
996 options.SetPrefixToken('@');
997 options.SetSourceSize(explicit_length);
Enrico Granata01dcaa32015-07-17 19:06:39 +0000998 options.SetNeedsZeroTermination(!has_explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000999 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granata01dcaa32015-07-17 19:06:39 +00001000 options.SetBinaryZeroIsTerminator(!has_explicit_length);
1001 if (has_explicit_length)
1002 return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
1003 else
1004 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +00001005 }
1006 else
1007 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001008 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001009 location = process_sp->ReadPointerFromMemory(location, error);
1010 if (error.Fail())
1011 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +00001012 if (has_explicit_length && !has_null)
1013 explicit_length++; // account for the fact that there is no NULL and we need to have one added
Enrico Granataebdc1ac2014-11-05 21:20:48 +00001014 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001015 options.SetLocation(location);
1016 options.SetProcessSP(process_sp);
1017 options.SetPrefixToken('@');
1018 options.SetStream(&stream);
1019 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +00001020 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001021 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +00001022 }
Enrico Granataf5196282012-09-04 18:48:21 +00001023}
1024
Enrico Granataf175ad12012-10-03 23:53:45 +00001025bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001026lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001027{
1028 TargetSP target_sp(valobj.GetTargetSP());
1029 if (!target_sp)
1030 return false;
1031 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001032 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1033 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001034 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001035 pointer_value += addr_size;
1036 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001037 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001038 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001039 if (!child_ptr_sp)
1040 return false;
1041 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001042 Error error;
1043 child_ptr_sp->GetData(data, error);
1044 if (error.Fail())
1045 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001046 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1047 child_sp->GetValueAsUnsigned(0);
1048 if (child_sp)
Enrico Granataf35bc632014-11-06 21:55:30 +00001049 return NSStringSummaryProvider(*child_sp, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001050 return false;
1051}
1052
1053bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001054lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001055{
Enrico Granataf35bc632014-11-06 21:55:30 +00001056 return NSAttributedStringSummaryProvider(valobj, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001057}
1058
1059bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001060lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf175ad12012-10-03 23:53:45 +00001061{
1062 stream.Printf("%s",valobj.GetObjectDescription());
1063 return true;
1064}
1065
Enrico Granatab5887262012-10-29 21:18:03 +00001066bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001067lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001068{
Greg Clayton57ee3062013-07-11 22:46:58 +00001069 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001070
1071 ValueObjectSP real_guy_sp = valobj.GetSP();
1072
Enrico Granata622be232014-10-21 20:52:14 +00001073 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001074 {
1075 Error err;
1076 real_guy_sp = valobj.Dereference(err);
1077 if (err.Fail() || !real_guy_sp)
1078 return false;
1079 }
Enrico Granata622be232014-10-21 20:52:14 +00001080 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001081 {
1082 real_guy_sp = valobj.GetChildAtIndex(0, true);
1083 if (!real_guy_sp)
1084 return false;
1085 }
1086 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1087 if (value == 0)
1088 {
1089 stream.Printf("NO");
1090 return true;
1091 }
1092 stream.Printf("YES");
1093 return true;
1094}
1095
1096template <bool is_sel_ptr>
1097bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001098lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001099{
Enrico Granata75dfb432013-02-15 00:06:04 +00001100 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001101
Greg Clayton57ee3062013-07-11 22:46:58 +00001102 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1103
1104 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001105 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001106
Enrico Granatab5887262012-10-29 21:18:03 +00001107 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1108
Enrico Granata75dfb432013-02-15 00:06:04 +00001109 if (is_sel_ptr)
1110 {
1111 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1112 if (data_address == LLDB_INVALID_ADDRESS)
1113 return false;
1114 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1115 }
1116 else
1117 {
1118 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001119 Error error;
1120 valobj.GetData(data, error);
1121 if (error.Fail())
1122 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001123 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1124 }
Enrico Granatab5887262012-10-29 21:18:03 +00001125
Enrico Granata75dfb432013-02-15 00:06:04 +00001126 if (!valobj_sp)
1127 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001128
1129 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1130 return true;
1131}
1132
Enrico Granata6d37cc62013-03-19 00:27:22 +00001133// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1134// this call gives the POSIX equivalent of the Cocoa epoch
1135time_t
Enrico Granata92373532013-03-19 22:58:48 +00001136lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001137{
1138 static time_t epoch = 0;
1139 if (!epoch)
1140 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001141#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001142 tzset();
1143 tm tm_epoch;
1144 tm_epoch.tm_sec = 0;
1145 tm_epoch.tm_hour = 0;
1146 tm_epoch.tm_min = 0;
1147 tm_epoch.tm_mon = 0;
1148 tm_epoch.tm_mday = 1;
1149 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1150 tm_epoch.tm_isdst = -1;
1151 tm_epoch.tm_gmtoff = 0;
1152 tm_epoch.tm_zone = NULL;
1153 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001154#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001155 }
1156 return epoch;
1157}
1158
Greg Claytonc7bece562013-01-25 18:06:21 +00001159size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001160lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001161{
1162 if (!item_name || !*item_name)
1163 return UINT32_MAX;
1164 if (*item_name != '[')
1165 return UINT32_MAX;
1166 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001167 char* endptr = NULL;
1168 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1169 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001170 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001171 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001172 return UINT32_MAX;
1173 return idx;
1174}
1175
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001176lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1177 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001178SyntheticChildrenFrontEnd(*valobj_sp.get()),
1179m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001180m_item_name(item_name),
1181m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001182{
1183 if (valobj_sp)
1184 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001185}
1186
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001187bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001188lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001189{
Enrico Granata6eca3552013-03-28 18:50:54 +00001190 m_item_sp.reset();
1191
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001192 ValueObjectSP valobj_sp = m_backend.GetSP();
1193 if (!valobj_sp)
1194 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001195
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001196 if (!valobj_sp)
1197 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001198
1199 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1200 if (!item_ptr)
1201 return false;
1202 if (item_ptr->GetValueAsUnsigned(0) == 0)
1203 return false;
1204 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001205 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granatae29df232014-12-09 19:51:20 +00001206 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001207 if (err.Fail())
1208 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001209 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001210}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001211
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001212size_t
1213lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1214{
1215 return 1;
1216}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001217
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001218lldb::ValueObjectSP
1219lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1220{
1221 if (idx == 0)
1222 return m_item_sp;
1223 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001224}
1225
1226bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001227lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001228{
1229 return true;
1230}
1231
1232size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001233lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001234{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001235 if (name == ConstString("item"))
1236 return 0;
1237 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001238}
1239
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001240lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001241{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001242}
1243
Enrico Granataf5196282012-09-04 18:48:21 +00001244template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001245lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab2698cd2012-09-13 18:27:09 +00001246
1247template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001248lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001249
1250template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001251lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001252
1253template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001254lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;