blob: 507d67114108a4b60a1d4f5ae7aac7c0e836a7f7 [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 Labathc33ae022015-06-08 22:27:10 +0000315 ClangASTContext* lldb_ast = valobj.GetClangType().GetTypeSystem()->AsClangASTContext();
316 clang::ASTContext* ast = lldb_ast ? lldb_ast->getASTContext() : nullptr;
Greg Clayton57ee3062013-07-11 22:46:58 +0000317
Enrico Granata38352042013-01-11 02:44:00 +0000318 if (!ast)
319 return false;
320
Greg Clayton57ee3062013-07-11 22:46:58 +0000321 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
Greg Clayton526ae042015-02-12 00:34:25 +0000322 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 +0000323
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000324 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000325 options.SetLocation(data_addr);
326 options.SetProcessSP(process_sp);
327 options.SetStream(&stream);
328 options.SetPrefixToken('L');
329
Enrico Granata38352042013-01-11 02:44:00 +0000330 switch (wchar_size)
331 {
332 case 8:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000333 return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000334 case 16:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000335 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000336 case 32:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000337 return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000338 default:
339 stream.Printf("size for wchar_t is not valid");
340 return true;
341 }
342 return true;
343}
344
345bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000346lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000347{
348 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000349 Error error;
350 valobj.GetData(data, error);
351
352 if (error.Fail())
353 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000354
355 std::string value;
356 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
357 if (!value.empty())
358 stream.Printf("%s ", value.c_str());
359
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000360 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000361 options.SetData(data);
362 options.SetStream(&stream);
363 options.SetPrefixToken('u');
364 options.SetQuote('\'');
365 options.SetSourceSize(1);
366
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);
391
392 return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000393}
394
395bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000396lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000397{
398 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000399 Error error;
400 valobj.GetData(data, error);
401
402 if (error.Fail())
403 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000404
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000405 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000406 options.SetData(data);
407 options.SetStream(&stream);
408 options.SetPrefixToken('L');
409 options.SetQuote('\'');
410 options.SetSourceSize(1);
Enrico Granata93d59662013-01-14 23:53:26 +0000411
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000412 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granataf68df122013-01-10 22:08:35 +0000413}
414
Enrico Granataa3962a72013-05-15 00:47:46 +0000415// the field layout in a libc++ string (cap, side, data or data, size, cap)
416enum LibcxxStringLayoutMode
417{
418 eLibcxxStringLayoutModeCSD = 0,
419 eLibcxxStringLayoutModeDSC = 1,
420 eLibcxxStringLayoutModeInvalid = 0xffff
421};
422
423// this function abstracts away the layout and mode details of a libc++ string
424// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000425static bool
426ExtractLibcxxStringInfo (ValueObject& valobj,
427 ValueObjectSP &location_sp,
428 uint64_t& size)
429{
430 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
431 if (!D)
432 return false;
433
Enrico Granataa3962a72013-05-15 00:47:46 +0000434 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
435
436 // this child should exist
437 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000438 return false;
439
Enrico Granataa3962a72013-05-15 00:47:46 +0000440 ConstString g_data_name("__data_");
441 ConstString g_size_name("__size_");
442 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
443 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
444 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000445
Enrico Granataa3962a72013-05-15 00:47:46 +0000446 if (layout == eLibcxxStringLayoutModeDSC)
447 {
448 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
449 if (!size_mode)
450 return false;
451
452 if (size_mode->GetName() != g_size_name)
453 {
454 // we are hitting the padding structure, move along
455 size_mode = D->GetChildAtIndexPath({1,1,1});
456 if (!size_mode)
457 return false;
458 }
459
460 size_mode_value = (size_mode->GetValueAsUnsigned(0));
461 short_mode = ((size_mode_value & 0x80) == 0);
462 }
463 else
464 {
465 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
466 if (!size_mode)
467 return false;
468
469 size_mode_value = (size_mode->GetValueAsUnsigned(0));
470 short_mode = ((size_mode_value & 1) == 0);
471 }
472
473 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000474 {
475 ValueObjectSP s(D->GetChildAtIndex(1, true));
476 if (!s)
477 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000478 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
479 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000480 return (location_sp.get() != nullptr);
481 }
482 else
483 {
484 ValueObjectSP l(D->GetChildAtIndex(0, true));
485 if (!l)
486 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000487 // we can use the layout_decider object as the data pointer
488 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000489 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
490 if (!size_vo || !location_sp)
491 return false;
492 size = size_vo->GetValueAsUnsigned(0);
493 return true;
494 }
495}
496
497bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000498lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata3309d882013-01-12 01:00:22 +0000499{
500 uint64_t size = 0;
501 ValueObjectSP location_sp((ValueObject*)nullptr);
502 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
503 return false;
504 if (size == 0)
505 {
506 stream.Printf("L\"\"");
507 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000508 }
Enrico Granata3309d882013-01-12 01:00:22 +0000509 if (!location_sp)
510 return false;
Enrico Granataf35bc632014-11-06 21:55:30 +0000511 return WCharStringSummaryProvider(*location_sp.get(), stream, options);
Enrico Granata3309d882013-01-12 01:00:22 +0000512}
513
514bool
Enrico Granata34042212014-11-18 22:54:45 +0000515lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000516{
517 uint64_t size = 0;
518 ValueObjectSP location_sp((ValueObject*)nullptr);
Enrico Granata2206b482014-10-30 18:27:31 +0000519
Enrico Granata3309d882013-01-12 01:00:22 +0000520 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
521 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000522
Enrico Granata3309d882013-01-12 01:00:22 +0000523 if (size == 0)
524 {
525 stream.Printf("\"\"");
526 return true;
527 }
Enrico Granata2206b482014-10-30 18:27:31 +0000528
Enrico Granata3309d882013-01-12 01:00:22 +0000529 if (!location_sp)
530 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000531
532 DataExtractor extractor;
Enrico Granata34042212014-11-18 22:54:45 +0000533 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
534 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
Enrico Granata2206b482014-10-30 18:27:31 +0000535 location_sp->GetPointeeData(extractor, 0, size);
536
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000537 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granata2206b482014-10-30 18:27:31 +0000538 options.SetData(extractor); // none of this matters for a string - pass some defaults
539 options.SetStream(&stream);
540 options.SetPrefixToken(0);
541 options.SetQuote('"');
542 options.SetSourceSize(size);
Enrico Granata2206b482014-10-30 18:27:31 +0000543 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
544
545 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000546}
547
Enrico Granata55900862013-03-15 18:55:30 +0000548bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000549lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata55900862013-03-15 18:55:30 +0000550{
551 ProcessSP process_sp = valobj.GetProcessSP();
552 if (!process_sp)
553 return false;
554
555 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
556
557 if (!runtime)
558 return false;
559
Greg Clayton03da4cc2013-04-19 21:31:16 +0000560 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000561
562 if (!descriptor.get() || !descriptor->IsValid())
563 return false;
564
565 const char* class_name = descriptor->GetClassName().GetCString();
566
567 if (!class_name || !*class_name)
568 return false;
569
570 stream.Printf("%s",class_name);
571 return true;
572}
573
Enrico Granatac76b97b2013-04-26 00:59:02 +0000574class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
575{
576public:
577 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
578 SyntheticChildrenFrontEnd(*valobj_sp.get())
579 {
580 }
581
582 virtual size_t
583 CalculateNumChildren ()
584 {
585 return 0;
586 }
587
588 virtual lldb::ValueObjectSP
589 GetChildAtIndex (size_t idx)
590 {
591 return lldb::ValueObjectSP();
592 }
593
594 virtual bool
595 Update()
596 {
597 return false;
598 }
599
600 virtual bool
601 MightHaveChildren ()
602 {
603 return false;
604 }
605
606 virtual size_t
607 GetIndexOfChildWithName (const ConstString &name)
608 {
609 return UINT32_MAX;
610 }
611
612 virtual
613 ~ObjCClassSyntheticChildrenFrontEnd ()
614 {
615 }
616};
617
618SyntheticChildrenFrontEnd*
619lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
620{
621 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
622}
623
Enrico Granataf5196282012-09-04 18:48:21 +0000624template<bool needs_at>
625bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000626lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf5196282012-09-04 18:48:21 +0000627{
628 ProcessSP process_sp = valobj.GetProcessSP();
629 if (!process_sp)
630 return false;
631
632 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
633
634 if (!runtime)
635 return false;
636
637 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
638
639 if (!descriptor.get() || !descriptor->IsValid())
640 return false;
641
642 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
643 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
644
645 if (!valobj_addr)
646 return false;
647
648 uint64_t value = 0;
649
650 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000651
652 if (!class_name || !*class_name)
653 return false;
654
Enrico Granataf5196282012-09-04 18:48:21 +0000655 if (!strcmp(class_name,"NSConcreteData") ||
656 !strcmp(class_name,"NSConcreteMutableData") ||
657 !strcmp(class_name,"__NSCFData"))
658 {
659 uint32_t offset = (is_64bit ? 16 : 8);
660 Error error;
661 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
662 if (error.Fail())
663 return false;
664 }
665 else
666 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000667 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000668 return false;
669 }
670
Daniel Malead01b2952012-11-29 21:49:15 +0000671 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000672 (needs_at ? "@\"" : ""),
673 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000674 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000675 (needs_at ? "\"" : ""));
676
677 return true;
678}
679
Enrico Granata87f00b42013-02-21 20:31:18 +0000680static bool
681ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
682 lldb::ProcessSP& process_sp,
683 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000684 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000685 Error* error = NULL,
686 size_t *data_read = NULL,
687 char prefix_token = '@',
688 char quote = '"')
689{
690 Error my_error;
691 size_t my_data_read;
692 if (!process_sp || location == 0)
693 return false;
694
Enrico Granata23ab35a2013-04-02 23:07:55 +0000695 if (!size)
696 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
697 else
698 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000699
700 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
701
702 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
703
704 if (error)
705 *error = my_error;
706 if (data_read)
707 *data_read = my_data_read;
708
709 if (my_error.Fail())
710 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000711
712 dest.Printf("%c%c",prefix_token,quote);
713
Enrico Granata87f00b42013-02-21 20:31:18 +0000714 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000715 dest.Printf("%s",(char*)buffer_sp->GetBytes());
716
717 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000718
719 return true;
720}
721
Enrico Granataf5196282012-09-04 18:48:21 +0000722bool
Jason Molenda705b1802014-06-13 02:37:02 +0000723lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
724{
725 if (!descriptor)
726 return false;
727 uint64_t len_bits = 0, data_bits = 0;
728 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
729 return false;
730
731 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
732 static const int g_SixbitMaxLen = 9;
733 static const int g_fiveBitMaxLen = 11;
734
735 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
736
737 if (len_bits > g_fiveBitMaxLen)
738 return false;
739
740 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
741 // this works under a few assumptions:
742 // little endian architecture
743 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
744 if (len_bits <= g_MaxNonBitmaskedLen)
745 {
746 stream.Printf("@\"%s\"",(const char*)&data_bits);
747 return true;
748 }
749
750 // if the data is bitmasked, we need to actually process the bytes
751 uint8_t bitmask = 0;
752 uint8_t shift_offset = 0;
753
754 if (len_bits <= g_SixbitMaxLen)
755 {
756 bitmask = 0x03f;
757 shift_offset = 6;
758 }
759 else
760 {
761 bitmask = 0x01f;
762 shift_offset = 5;
763 }
764
765 std::vector<uint8_t> bytes;
766 bytes.resize(len_bits);
767 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
768 {
769 uint8_t packed = data_bits & bitmask;
770 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
771 }
772
773 stream.Printf("@\"%s\"",&bytes[0]);
774 return true;
775}
776
Enrico Granata76b08d52014-10-29 23:08:02 +0000777static ClangASTType
778GetNSPathStore2Type (Target &target)
779{
780 static ConstString g_type_name("__lldb_autogen_nspathstore2");
781
782 ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
783
784 if (!ast_ctx)
785 return ClangASTType();
786
787 ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
788 ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
789
790 return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
791 {"isa",voidstar},
792 {"lengthAndRef",uint32},
793 {"buffer",voidstar}
794 });
795}
796
Jason Molenda705b1802014-06-13 02:37:02 +0000797bool
Enrico Granata34042212014-11-18 22:54:45 +0000798lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granataf5196282012-09-04 18:48:21 +0000799{
800 ProcessSP process_sp = valobj.GetProcessSP();
801 if (!process_sp)
802 return false;
803
804 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
805
806 if (!runtime)
807 return false;
808
809 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
810
811 if (!descriptor.get() || !descriptor->IsValid())
812 return false;
813
814 uint32_t ptr_size = process_sp->GetAddressByteSize();
815
816 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
817
818 if (!valobj_addr)
819 return false;
820
821 const char* class_name = descriptor->GetClassName().GetCString();
822
Enrico Granata60b81df2012-09-29 00:45:53 +0000823 if (!class_name || !*class_name)
824 return false;
825
Jason Molenda705b1802014-06-13 02:37:02 +0000826 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
827 // for a tagged pointer, the descriptor has everything we need
828 if (is_tagged_ptr)
829 return NSTaggedString_SummaryProvider(descriptor, stream);
830
831 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +0000832 uint64_t info_bits_location = valobj_addr + ptr_size;
833 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
834 info_bits_location += 3;
835
Enrico Granata87f00b42013-02-21 20:31:18 +0000836 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000837
838 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
839 if (error.Fail())
840 return false;
841
842 bool is_mutable = (info_bits & 1) == 1;
843 bool is_inline = (info_bits & 0x60) == 0;
844 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
845 bool is_unicode = (info_bits & 0x10) == 0x10;
846 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000847 bool has_null = (info_bits & 8) == 8;
848
849 size_t explicit_length = 0;
850 if (!has_null && has_explicit_length && !is_special)
851 {
852 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000853 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000854 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
855 else if (is_inline)
856 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000857 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000858 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
859 else
860 explicit_length_offset = 0;
861
862 if (explicit_length_offset)
863 {
864 explicit_length_offset = valobj_addr + explicit_length_offset;
865 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
866 }
867 }
868
Enrico Granataf5196282012-09-04 18:48:21 +0000869 if (strcmp(class_name,"NSString") &&
870 strcmp(class_name,"CFStringRef") &&
871 strcmp(class_name,"CFMutableStringRef") &&
872 strcmp(class_name,"__NSCFConstantString") &&
873 strcmp(class_name,"__NSCFString") &&
874 strcmp(class_name,"NSCFConstantString") &&
875 strcmp(class_name,"NSCFString") &&
876 strcmp(class_name,"NSPathStore2"))
877 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000878 // not one of us - but tell me class name
879 stream.Printf("class name = %s",class_name);
880 return true;
Enrico Granataf5196282012-09-04 18:48:21 +0000881 }
882
883 if (is_mutable)
884 {
885 uint64_t location = 2 * ptr_size + valobj_addr;
886 location = process_sp->ReadPointerFromMemory(location, error);
887 if (error.Fail())
888 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000889 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +0000890 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000891 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000892 options.SetLocation(location);
893 options.SetProcessSP(process_sp);
894 options.SetStream(&stream);
895 options.SetPrefixToken('@');
896 options.SetQuote('"');
897 options.SetSourceSize(explicit_length);
898 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000899 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000900 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata56768392013-04-23 20:05:05 +0000901 }
Enrico Granataf5196282012-09-04 18:48:21 +0000902 else
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000903 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000904 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000905 options.SetLocation(location+1);
906 options.SetProcessSP(process_sp);
907 options.SetStream(&stream);
908 options.SetPrefixToken('@');
909 options.SetSourceSize(explicit_length);
910 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000911 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000912 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
913 }
Enrico Granataf5196282012-09-04 18:48:21 +0000914 }
915 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
916 {
917 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000918 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +0000919 }
920 else if (is_unicode)
921 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000922 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000923 if (is_inline)
924 {
925 if (!has_explicit_length)
926 {
927 stream.Printf("found new combo");
928 return true;
929 }
930 else
931 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +0000932 }
Enrico Granataf5196282012-09-04 18:48:21 +0000933 else
934 {
935 location = process_sp->ReadPointerFromMemory(location, error);
936 if (error.Fail())
937 return false;
938 }
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000939 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000940 options.SetLocation(location);
941 options.SetProcessSP(process_sp);
942 options.SetStream(&stream);
943 options.SetPrefixToken('@');
944 options.SetQuote('"');
945 options.SetSourceSize(explicit_length);
946 options.SetNeedsZeroTermination(has_explicit_length == 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::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000949 }
950 else if (is_special)
951 {
Enrico Granata76b08d52014-10-29 23:08:02 +0000952 ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
953 explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
954 lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
955
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000956 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000957 options.SetLocation(location);
958 options.SetProcessSP(process_sp);
959 options.SetStream(&stream);
960 options.SetPrefixToken('@');
961 options.SetQuote('"');
962 options.SetSourceSize(explicit_length);
963 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000964 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000965 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000966 }
967 else if (is_inline)
968 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000969 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000970 if (!has_explicit_length)
971 location++;
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000972 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000973 options.SetLocation(location);
974 options.SetProcessSP(process_sp);
975 options.SetStream(&stream);
976 options.SetPrefixToken('@');
977 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000978 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000979 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000980 }
981 else
982 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000983 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000984 location = process_sp->ReadPointerFromMemory(location, error);
985 if (error.Fail())
986 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +0000987 if (has_explicit_length && !has_null)
988 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 +0000989 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000990 options.SetLocation(location);
991 options.SetProcessSP(process_sp);
992 options.SetPrefixToken('@');
993 options.SetStream(&stream);
994 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000995 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000996 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000997 }
Enrico Granataf5196282012-09-04 18:48:21 +0000998}
999
Enrico Granataf175ad12012-10-03 23:53:45 +00001000bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001001lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001002{
1003 TargetSP target_sp(valobj.GetTargetSP());
1004 if (!target_sp)
1005 return false;
1006 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001007 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1008 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001009 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001010 pointer_value += addr_size;
1011 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001012 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001013 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001014 if (!child_ptr_sp)
1015 return false;
1016 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001017 Error error;
1018 child_ptr_sp->GetData(data, error);
1019 if (error.Fail())
1020 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001021 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1022 child_sp->GetValueAsUnsigned(0);
1023 if (child_sp)
Enrico Granataf35bc632014-11-06 21:55:30 +00001024 return NSStringSummaryProvider(*child_sp, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001025 return false;
1026}
1027
1028bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001029lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001030{
Enrico Granataf35bc632014-11-06 21:55:30 +00001031 return NSAttributedStringSummaryProvider(valobj, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001032}
1033
1034bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001035lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf175ad12012-10-03 23:53:45 +00001036{
1037 stream.Printf("%s",valobj.GetObjectDescription());
1038 return true;
1039}
1040
Enrico Granatab5887262012-10-29 21:18:03 +00001041bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001042lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001043{
Greg Clayton57ee3062013-07-11 22:46:58 +00001044 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001045
1046 ValueObjectSP real_guy_sp = valobj.GetSP();
1047
Enrico Granata622be232014-10-21 20:52:14 +00001048 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001049 {
1050 Error err;
1051 real_guy_sp = valobj.Dereference(err);
1052 if (err.Fail() || !real_guy_sp)
1053 return false;
1054 }
Enrico Granata622be232014-10-21 20:52:14 +00001055 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001056 {
1057 real_guy_sp = valobj.GetChildAtIndex(0, true);
1058 if (!real_guy_sp)
1059 return false;
1060 }
1061 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1062 if (value == 0)
1063 {
1064 stream.Printf("NO");
1065 return true;
1066 }
1067 stream.Printf("YES");
1068 return true;
1069}
1070
1071template <bool is_sel_ptr>
1072bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001073lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001074{
Enrico Granata75dfb432013-02-15 00:06:04 +00001075 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001076
Greg Clayton57ee3062013-07-11 22:46:58 +00001077 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1078
1079 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001080 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001081
Enrico Granatab5887262012-10-29 21:18:03 +00001082 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1083
Enrico Granata75dfb432013-02-15 00:06:04 +00001084 if (is_sel_ptr)
1085 {
1086 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1087 if (data_address == LLDB_INVALID_ADDRESS)
1088 return false;
1089 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1090 }
1091 else
1092 {
1093 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001094 Error error;
1095 valobj.GetData(data, error);
1096 if (error.Fail())
1097 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001098 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1099 }
Enrico Granatab5887262012-10-29 21:18:03 +00001100
Enrico Granata75dfb432013-02-15 00:06:04 +00001101 if (!valobj_sp)
1102 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001103
1104 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1105 return true;
1106}
1107
Enrico Granata6d37cc62013-03-19 00:27:22 +00001108// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1109// this call gives the POSIX equivalent of the Cocoa epoch
1110time_t
Enrico Granata92373532013-03-19 22:58:48 +00001111lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001112{
1113 static time_t epoch = 0;
1114 if (!epoch)
1115 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001116#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001117 tzset();
1118 tm tm_epoch;
1119 tm_epoch.tm_sec = 0;
1120 tm_epoch.tm_hour = 0;
1121 tm_epoch.tm_min = 0;
1122 tm_epoch.tm_mon = 0;
1123 tm_epoch.tm_mday = 1;
1124 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1125 tm_epoch.tm_isdst = -1;
1126 tm_epoch.tm_gmtoff = 0;
1127 tm_epoch.tm_zone = NULL;
1128 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001129#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001130 }
1131 return epoch;
1132}
1133
Greg Claytonc7bece562013-01-25 18:06:21 +00001134size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001135lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001136{
1137 if (!item_name || !*item_name)
1138 return UINT32_MAX;
1139 if (*item_name != '[')
1140 return UINT32_MAX;
1141 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001142 char* endptr = NULL;
1143 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1144 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001145 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001146 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001147 return UINT32_MAX;
1148 return idx;
1149}
1150
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001151lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1152 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001153SyntheticChildrenFrontEnd(*valobj_sp.get()),
1154m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001155m_item_name(item_name),
1156m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001157{
1158 if (valobj_sp)
1159 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001160}
1161
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001162bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001163lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001164{
Enrico Granata6eca3552013-03-28 18:50:54 +00001165 m_item_sp.reset();
1166
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001167 ValueObjectSP valobj_sp = m_backend.GetSP();
1168 if (!valobj_sp)
1169 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001170
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001171 if (!valobj_sp)
1172 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001173
1174 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1175 if (!item_ptr)
1176 return false;
1177 if (item_ptr->GetValueAsUnsigned(0) == 0)
1178 return false;
1179 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001180 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granatae29df232014-12-09 19:51:20 +00001181 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001182 if (err.Fail())
1183 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001184 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001185}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001186
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001187size_t
1188lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1189{
1190 return 1;
1191}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001192
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001193lldb::ValueObjectSP
1194lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1195{
1196 if (idx == 0)
1197 return m_item_sp;
1198 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001199}
1200
1201bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001202lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001203{
1204 return true;
1205}
1206
1207size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001208lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001209{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001210 if (name == ConstString("item"))
1211 return 0;
1212 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001213}
1214
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001215lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001216{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001217}
1218
Enrico Granataf5196282012-09-04 18:48:21 +00001219template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001220lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab2698cd2012-09-13 18:27:09 +00001221
1222template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001223lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001224
1225template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001226lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001227
1228template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001229lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;