blob: 611ebedba56d7d0344b80be98b5a40599ba61bf2 [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);
365
366 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000367}
368
369bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000370lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000371{
372 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000373 Error error;
374 valobj.GetData(data, error);
375
376 if (error.Fail())
377 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000378
379 std::string value;
380 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
381 if (!value.empty())
382 stream.Printf("%s ", value.c_str());
383
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000384 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000385 options.SetData(data);
386 options.SetStream(&stream);
387 options.SetPrefixToken('U');
388 options.SetQuote('\'');
389 options.SetSourceSize(1);
390
391 return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000392}
393
394bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000395lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000396{
397 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000398 Error error;
399 valobj.GetData(data, error);
400
401 if (error.Fail())
402 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000403
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000404 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000405 options.SetData(data);
406 options.SetStream(&stream);
407 options.SetPrefixToken('L');
408 options.SetQuote('\'');
409 options.SetSourceSize(1);
Enrico Granata93d59662013-01-14 23:53:26 +0000410
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000411 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granataf68df122013-01-10 22:08:35 +0000412}
413
Enrico Granataa3962a72013-05-15 00:47:46 +0000414// the field layout in a libc++ string (cap, side, data or data, size, cap)
415enum LibcxxStringLayoutMode
416{
417 eLibcxxStringLayoutModeCSD = 0,
418 eLibcxxStringLayoutModeDSC = 1,
419 eLibcxxStringLayoutModeInvalid = 0xffff
420};
421
422// this function abstracts away the layout and mode details of a libc++ string
423// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000424static bool
425ExtractLibcxxStringInfo (ValueObject& valobj,
426 ValueObjectSP &location_sp,
427 uint64_t& size)
428{
429 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
430 if (!D)
431 return false;
432
Enrico Granataa3962a72013-05-15 00:47:46 +0000433 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
434
435 // this child should exist
436 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000437 return false;
438
Enrico Granataa3962a72013-05-15 00:47:46 +0000439 ConstString g_data_name("__data_");
440 ConstString g_size_name("__size_");
441 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
442 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
443 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000444
Enrico Granataa3962a72013-05-15 00:47:46 +0000445 if (layout == eLibcxxStringLayoutModeDSC)
446 {
447 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
448 if (!size_mode)
449 return false;
450
451 if (size_mode->GetName() != g_size_name)
452 {
453 // we are hitting the padding structure, move along
454 size_mode = D->GetChildAtIndexPath({1,1,1});
455 if (!size_mode)
456 return false;
457 }
458
459 size_mode_value = (size_mode->GetValueAsUnsigned(0));
460 short_mode = ((size_mode_value & 0x80) == 0);
461 }
462 else
463 {
464 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
465 if (!size_mode)
466 return false;
467
468 size_mode_value = (size_mode->GetValueAsUnsigned(0));
469 short_mode = ((size_mode_value & 1) == 0);
470 }
471
472 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000473 {
474 ValueObjectSP s(D->GetChildAtIndex(1, true));
475 if (!s)
476 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000477 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
478 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000479 return (location_sp.get() != nullptr);
480 }
481 else
482 {
483 ValueObjectSP l(D->GetChildAtIndex(0, true));
484 if (!l)
485 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000486 // we can use the layout_decider object as the data pointer
487 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000488 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
489 if (!size_vo || !location_sp)
490 return false;
491 size = size_vo->GetValueAsUnsigned(0);
492 return true;
493 }
494}
495
496bool
Enrico Granata8101f572015-07-17 01:56:25 +0000497lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000498{
499 uint64_t size = 0;
500 ValueObjectSP location_sp((ValueObject*)nullptr);
501 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
502 return false;
503 if (size == 0)
504 {
505 stream.Printf("L\"\"");
506 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000507 }
Enrico Granata3309d882013-01-12 01:00:22 +0000508 if (!location_sp)
509 return false;
Enrico Granata8101f572015-07-17 01:56:25 +0000510
511 DataExtractor extractor;
512 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
513 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
514 location_sp->GetPointeeData(extractor, 0, size);
515
516 // std::wstring::size() is measured in 'characters', not bytes
517 auto wchar_t_size = valobj.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
518
519 ReadBufferAndDumpToStreamOptions options(valobj);
520 options.SetData(extractor);
521 options.SetStream(&stream);
522 options.SetPrefixToken('L');
523 options.SetQuote('"');
524 options.SetSourceSize(size);
525 options.SetBinaryZeroIsTerminator(false);
526
527 switch (wchar_t_size)
528 {
529 case 1:
530 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF8>(options);
531 break;
532
533 case 2:
534 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF16>(options);
535 break;
536
537 case 4:
538 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::UTF32>(options);
539 break;
540
541 default:
542 stream.Printf("size for wchar_t is not valid");
543 return true;
544 }
545
546 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000547}
548
549bool
Enrico Granata34042212014-11-18 22:54:45 +0000550lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000551{
552 uint64_t size = 0;
553 ValueObjectSP location_sp((ValueObject*)nullptr);
Enrico Granata2206b482014-10-30 18:27:31 +0000554
Enrico Granata3309d882013-01-12 01:00:22 +0000555 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
556 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000557
Enrico Granata3309d882013-01-12 01:00:22 +0000558 if (size == 0)
559 {
560 stream.Printf("\"\"");
561 return true;
562 }
Enrico Granata2206b482014-10-30 18:27:31 +0000563
Enrico Granata3309d882013-01-12 01:00:22 +0000564 if (!location_sp)
565 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000566
567 DataExtractor extractor;
Enrico Granata34042212014-11-18 22:54:45 +0000568 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
569 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
Enrico Granata2206b482014-10-30 18:27:31 +0000570 location_sp->GetPointeeData(extractor, 0, size);
571
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000572 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granata8101f572015-07-17 01:56:25 +0000573 options.SetData(extractor);
Enrico Granata2206b482014-10-30 18:27:31 +0000574 options.SetStream(&stream);
575 options.SetPrefixToken(0);
576 options.SetQuote('"');
577 options.SetSourceSize(size);
Enrico Granatad07f7552015-07-17 01:03:59 +0000578 options.SetBinaryZeroIsTerminator(false);
Enrico Granata2206b482014-10-30 18:27:31 +0000579 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
580
581 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000582}
583
Enrico Granata55900862013-03-15 18:55:30 +0000584bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000585lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata55900862013-03-15 18:55:30 +0000586{
587 ProcessSP process_sp = valobj.GetProcessSP();
588 if (!process_sp)
589 return false;
590
591 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
592
593 if (!runtime)
594 return false;
595
Greg Clayton03da4cc2013-04-19 21:31:16 +0000596 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000597
598 if (!descriptor.get() || !descriptor->IsValid())
599 return false;
600
601 const char* class_name = descriptor->GetClassName().GetCString();
602
603 if (!class_name || !*class_name)
604 return false;
605
606 stream.Printf("%s",class_name);
607 return true;
608}
609
Enrico Granatac76b97b2013-04-26 00:59:02 +0000610class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
611{
612public:
613 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
614 SyntheticChildrenFrontEnd(*valobj_sp.get())
615 {
616 }
617
618 virtual size_t
619 CalculateNumChildren ()
620 {
621 return 0;
622 }
623
624 virtual lldb::ValueObjectSP
625 GetChildAtIndex (size_t idx)
626 {
627 return lldb::ValueObjectSP();
628 }
629
630 virtual bool
631 Update()
632 {
633 return false;
634 }
635
636 virtual bool
637 MightHaveChildren ()
638 {
639 return false;
640 }
641
642 virtual size_t
643 GetIndexOfChildWithName (const ConstString &name)
644 {
645 return UINT32_MAX;
646 }
647
648 virtual
649 ~ObjCClassSyntheticChildrenFrontEnd ()
650 {
651 }
652};
653
654SyntheticChildrenFrontEnd*
655lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
656{
657 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
658}
659
Enrico Granataf5196282012-09-04 18:48:21 +0000660template<bool needs_at>
661bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000662lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf5196282012-09-04 18:48:21 +0000663{
664 ProcessSP process_sp = valobj.GetProcessSP();
665 if (!process_sp)
666 return false;
667
668 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
669
670 if (!runtime)
671 return false;
672
673 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
674
675 if (!descriptor.get() || !descriptor->IsValid())
676 return false;
677
678 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
679 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
680
681 if (!valobj_addr)
682 return false;
683
684 uint64_t value = 0;
685
686 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000687
688 if (!class_name || !*class_name)
689 return false;
690
Enrico Granataf5196282012-09-04 18:48:21 +0000691 if (!strcmp(class_name,"NSConcreteData") ||
692 !strcmp(class_name,"NSConcreteMutableData") ||
693 !strcmp(class_name,"__NSCFData"))
694 {
695 uint32_t offset = (is_64bit ? 16 : 8);
696 Error error;
697 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
698 if (error.Fail())
699 return false;
700 }
701 else
702 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000703 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000704 return false;
705 }
706
Daniel Malead01b2952012-11-29 21:49:15 +0000707 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000708 (needs_at ? "@\"" : ""),
709 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000710 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000711 (needs_at ? "\"" : ""));
712
713 return true;
714}
715
Enrico Granata87f00b42013-02-21 20:31:18 +0000716static bool
717ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
718 lldb::ProcessSP& process_sp,
719 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000720 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000721 Error* error = NULL,
722 size_t *data_read = NULL,
723 char prefix_token = '@',
724 char quote = '"')
725{
726 Error my_error;
727 size_t my_data_read;
728 if (!process_sp || location == 0)
729 return false;
730
Enrico Granata23ab35a2013-04-02 23:07:55 +0000731 if (!size)
732 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
733 else
734 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000735
736 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
737
738 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
739
740 if (error)
741 *error = my_error;
742 if (data_read)
743 *data_read = my_data_read;
744
745 if (my_error.Fail())
746 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000747
748 dest.Printf("%c%c",prefix_token,quote);
749
Enrico Granata87f00b42013-02-21 20:31:18 +0000750 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000751 dest.Printf("%s",(char*)buffer_sp->GetBytes());
752
753 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000754
755 return true;
756}
757
Enrico Granataf5196282012-09-04 18:48:21 +0000758bool
Jason Molenda705b1802014-06-13 02:37:02 +0000759lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
760{
761 if (!descriptor)
762 return false;
763 uint64_t len_bits = 0, data_bits = 0;
764 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
765 return false;
766
767 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
768 static const int g_SixbitMaxLen = 9;
769 static const int g_fiveBitMaxLen = 11;
770
771 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
772
773 if (len_bits > g_fiveBitMaxLen)
774 return false;
775
776 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
777 // this works under a few assumptions:
778 // little endian architecture
779 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
780 if (len_bits <= g_MaxNonBitmaskedLen)
781 {
782 stream.Printf("@\"%s\"",(const char*)&data_bits);
783 return true;
784 }
785
786 // if the data is bitmasked, we need to actually process the bytes
787 uint8_t bitmask = 0;
788 uint8_t shift_offset = 0;
789
790 if (len_bits <= g_SixbitMaxLen)
791 {
792 bitmask = 0x03f;
793 shift_offset = 6;
794 }
795 else
796 {
797 bitmask = 0x01f;
798 shift_offset = 5;
799 }
800
801 std::vector<uint8_t> bytes;
802 bytes.resize(len_bits);
803 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
804 {
805 uint8_t packed = data_bits & bitmask;
806 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
807 }
808
809 stream.Printf("@\"%s\"",&bytes[0]);
810 return true;
811}
812
Enrico Granata76b08d52014-10-29 23:08:02 +0000813static ClangASTType
814GetNSPathStore2Type (Target &target)
815{
816 static ConstString g_type_name("__lldb_autogen_nspathstore2");
817
818 ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
819
820 if (!ast_ctx)
821 return ClangASTType();
822
823 ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
824 ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
825
826 return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
827 {"isa",voidstar},
828 {"lengthAndRef",uint32},
829 {"buffer",voidstar}
830 });
831}
832
Jason Molenda705b1802014-06-13 02:37:02 +0000833bool
Enrico Granata34042212014-11-18 22:54:45 +0000834lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granataf5196282012-09-04 18:48:21 +0000835{
836 ProcessSP process_sp = valobj.GetProcessSP();
837 if (!process_sp)
838 return false;
839
840 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
841
842 if (!runtime)
843 return false;
844
845 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
846
847 if (!descriptor.get() || !descriptor->IsValid())
848 return false;
849
850 uint32_t ptr_size = process_sp->GetAddressByteSize();
851
852 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
853
854 if (!valobj_addr)
855 return false;
856
857 const char* class_name = descriptor->GetClassName().GetCString();
858
Enrico Granata60b81df2012-09-29 00:45:53 +0000859 if (!class_name || !*class_name)
860 return false;
861
Jason Molenda705b1802014-06-13 02:37:02 +0000862 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
863 // for a tagged pointer, the descriptor has everything we need
864 if (is_tagged_ptr)
865 return NSTaggedString_SummaryProvider(descriptor, stream);
866
867 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +0000868 uint64_t info_bits_location = valobj_addr + ptr_size;
869 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
870 info_bits_location += 3;
871
Enrico Granata87f00b42013-02-21 20:31:18 +0000872 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000873
874 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
875 if (error.Fail())
876 return false;
877
878 bool is_mutable = (info_bits & 1) == 1;
879 bool is_inline = (info_bits & 0x60) == 0;
880 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
881 bool is_unicode = (info_bits & 0x10) == 0x10;
882 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000883 bool has_null = (info_bits & 8) == 8;
884
885 size_t explicit_length = 0;
886 if (!has_null && has_explicit_length && !is_special)
887 {
888 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000889 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000890 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
891 else if (is_inline)
892 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000893 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000894 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
895 else
896 explicit_length_offset = 0;
897
898 if (explicit_length_offset)
899 {
900 explicit_length_offset = valobj_addr + explicit_length_offset;
901 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
902 }
903 }
904
Enrico Granataf5196282012-09-04 18:48:21 +0000905 if (strcmp(class_name,"NSString") &&
906 strcmp(class_name,"CFStringRef") &&
907 strcmp(class_name,"CFMutableStringRef") &&
908 strcmp(class_name,"__NSCFConstantString") &&
909 strcmp(class_name,"__NSCFString") &&
910 strcmp(class_name,"NSCFConstantString") &&
911 strcmp(class_name,"NSCFString") &&
912 strcmp(class_name,"NSPathStore2"))
913 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000914 // not one of us - but tell me class name
915 stream.Printf("class name = %s",class_name);
916 return true;
Enrico Granataf5196282012-09-04 18:48:21 +0000917 }
918
919 if (is_mutable)
920 {
921 uint64_t location = 2 * ptr_size + valobj_addr;
922 location = process_sp->ReadPointerFromMemory(location, error);
923 if (error.Fail())
924 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000925 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +0000926 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000927 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000928 options.SetLocation(location);
929 options.SetProcessSP(process_sp);
930 options.SetStream(&stream);
931 options.SetPrefixToken('@');
932 options.SetQuote('"');
933 options.SetSourceSize(explicit_length);
934 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000935 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000936 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata56768392013-04-23 20:05:05 +0000937 }
Enrico Granataf5196282012-09-04 18:48:21 +0000938 else
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000939 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000940 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000941 options.SetLocation(location+1);
942 options.SetProcessSP(process_sp);
943 options.SetStream(&stream);
944 options.SetPrefixToken('@');
945 options.SetSourceSize(explicit_length);
946 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000947 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000948 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
949 }
Enrico Granataf5196282012-09-04 18:48:21 +0000950 }
951 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
952 {
953 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000954 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +0000955 }
956 else if (is_unicode)
957 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000958 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000959 if (is_inline)
960 {
961 if (!has_explicit_length)
962 {
963 stream.Printf("found new combo");
964 return true;
965 }
966 else
967 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +0000968 }
Enrico Granataf5196282012-09-04 18:48:21 +0000969 else
970 {
971 location = process_sp->ReadPointerFromMemory(location, error);
972 if (error.Fail())
973 return false;
974 }
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000975 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000976 options.SetLocation(location);
977 options.SetProcessSP(process_sp);
978 options.SetStream(&stream);
979 options.SetPrefixToken('@');
980 options.SetQuote('"');
981 options.SetSourceSize(explicit_length);
982 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000983 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000984 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000985 }
986 else if (is_special)
987 {
Enrico Granata76b08d52014-10-29 23:08:02 +0000988 ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
989 explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
990 lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
991
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000992 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000993 options.SetLocation(location);
994 options.SetProcessSP(process_sp);
995 options.SetStream(&stream);
996 options.SetPrefixToken('@');
997 options.SetQuote('"');
998 options.SetSourceSize(explicit_length);
999 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +00001000 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001001 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001002 }
1003 else if (is_inline)
1004 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001005 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001006 if (!has_explicit_length)
1007 location++;
Enrico Granataebdc1ac2014-11-05 21:20:48 +00001008 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001009 options.SetLocation(location);
1010 options.SetProcessSP(process_sp);
1011 options.SetStream(&stream);
1012 options.SetPrefixToken('@');
1013 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +00001014 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001015 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +00001016 }
1017 else
1018 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001019 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001020 location = process_sp->ReadPointerFromMemory(location, error);
1021 if (error.Fail())
1022 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +00001023 if (has_explicit_length && !has_null)
1024 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 +00001025 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001026 options.SetLocation(location);
1027 options.SetProcessSP(process_sp);
1028 options.SetPrefixToken('@');
1029 options.SetStream(&stream);
1030 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +00001031 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001032 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +00001033 }
Enrico Granataf5196282012-09-04 18:48:21 +00001034}
1035
Enrico Granataf175ad12012-10-03 23:53:45 +00001036bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001037lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001038{
1039 TargetSP target_sp(valobj.GetTargetSP());
1040 if (!target_sp)
1041 return false;
1042 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001043 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1044 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001045 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001046 pointer_value += addr_size;
1047 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001048 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001049 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001050 if (!child_ptr_sp)
1051 return false;
1052 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001053 Error error;
1054 child_ptr_sp->GetData(data, error);
1055 if (error.Fail())
1056 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001057 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1058 child_sp->GetValueAsUnsigned(0);
1059 if (child_sp)
Enrico Granataf35bc632014-11-06 21:55:30 +00001060 return NSStringSummaryProvider(*child_sp, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001061 return false;
1062}
1063
1064bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001065lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001066{
Enrico Granataf35bc632014-11-06 21:55:30 +00001067 return NSAttributedStringSummaryProvider(valobj, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001068}
1069
1070bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001071lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf175ad12012-10-03 23:53:45 +00001072{
1073 stream.Printf("%s",valobj.GetObjectDescription());
1074 return true;
1075}
1076
Enrico Granatab5887262012-10-29 21:18:03 +00001077bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001078lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001079{
Greg Clayton57ee3062013-07-11 22:46:58 +00001080 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001081
1082 ValueObjectSP real_guy_sp = valobj.GetSP();
1083
Enrico Granata622be232014-10-21 20:52:14 +00001084 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001085 {
1086 Error err;
1087 real_guy_sp = valobj.Dereference(err);
1088 if (err.Fail() || !real_guy_sp)
1089 return false;
1090 }
Enrico Granata622be232014-10-21 20:52:14 +00001091 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001092 {
1093 real_guy_sp = valobj.GetChildAtIndex(0, true);
1094 if (!real_guy_sp)
1095 return false;
1096 }
1097 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1098 if (value == 0)
1099 {
1100 stream.Printf("NO");
1101 return true;
1102 }
1103 stream.Printf("YES");
1104 return true;
1105}
1106
1107template <bool is_sel_ptr>
1108bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001109lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001110{
Enrico Granata75dfb432013-02-15 00:06:04 +00001111 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001112
Greg Clayton57ee3062013-07-11 22:46:58 +00001113 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1114
1115 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001116 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001117
Enrico Granatab5887262012-10-29 21:18:03 +00001118 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1119
Enrico Granata75dfb432013-02-15 00:06:04 +00001120 if (is_sel_ptr)
1121 {
1122 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1123 if (data_address == LLDB_INVALID_ADDRESS)
1124 return false;
1125 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1126 }
1127 else
1128 {
1129 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001130 Error error;
1131 valobj.GetData(data, error);
1132 if (error.Fail())
1133 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001134 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1135 }
Enrico Granatab5887262012-10-29 21:18:03 +00001136
Enrico Granata75dfb432013-02-15 00:06:04 +00001137 if (!valobj_sp)
1138 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001139
1140 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1141 return true;
1142}
1143
Enrico Granata6d37cc62013-03-19 00:27:22 +00001144// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1145// this call gives the POSIX equivalent of the Cocoa epoch
1146time_t
Enrico Granata92373532013-03-19 22:58:48 +00001147lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001148{
1149 static time_t epoch = 0;
1150 if (!epoch)
1151 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001152#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001153 tzset();
1154 tm tm_epoch;
1155 tm_epoch.tm_sec = 0;
1156 tm_epoch.tm_hour = 0;
1157 tm_epoch.tm_min = 0;
1158 tm_epoch.tm_mon = 0;
1159 tm_epoch.tm_mday = 1;
1160 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1161 tm_epoch.tm_isdst = -1;
1162 tm_epoch.tm_gmtoff = 0;
1163 tm_epoch.tm_zone = NULL;
1164 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001165#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001166 }
1167 return epoch;
1168}
1169
Greg Claytonc7bece562013-01-25 18:06:21 +00001170size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001171lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001172{
1173 if (!item_name || !*item_name)
1174 return UINT32_MAX;
1175 if (*item_name != '[')
1176 return UINT32_MAX;
1177 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001178 char* endptr = NULL;
1179 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1180 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001181 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001182 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001183 return UINT32_MAX;
1184 return idx;
1185}
1186
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001187lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1188 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001189SyntheticChildrenFrontEnd(*valobj_sp.get()),
1190m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001191m_item_name(item_name),
1192m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001193{
1194 if (valobj_sp)
1195 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001196}
1197
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001198bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001199lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001200{
Enrico Granata6eca3552013-03-28 18:50:54 +00001201 m_item_sp.reset();
1202
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001203 ValueObjectSP valobj_sp = m_backend.GetSP();
1204 if (!valobj_sp)
1205 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001206
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001207 if (!valobj_sp)
1208 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001209
1210 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1211 if (!item_ptr)
1212 return false;
1213 if (item_ptr->GetValueAsUnsigned(0) == 0)
1214 return false;
1215 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001216 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granatae29df232014-12-09 19:51:20 +00001217 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001218 if (err.Fail())
1219 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001220 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001221}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001222
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001223size_t
1224lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1225{
1226 return 1;
1227}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001228
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001229lldb::ValueObjectSP
1230lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1231{
1232 if (idx == 0)
1233 return m_item_sp;
1234 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001235}
1236
1237bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001238lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001239{
1240 return true;
1241}
1242
1243size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001244lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001245{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001246 if (name == ConstString("item"))
1247 return 0;
1248 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001249}
1250
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001251lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001252{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001253}
1254
Enrico Granataf5196282012-09-04 18:48:21 +00001255template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001256lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab2698cd2012-09-13 18:27:09 +00001257
1258template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001259lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001260
1261template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001262lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001263
1264template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001265lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;