blob: 04cdadf5a98fe5c343c6ceb45c79aa87ff91be5b [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
Matt Kopecef143712013-06-03 18:00:07 +000010#include "lldb/lldb-python.h"
11
Enrico Granata5548cb52013-01-28 23:47:25 +000012#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granataca6c8ee2014-10-30 01:45:39 +000013#include "lldb/DataFormatters/StringPrinter.h"
Enrico Granata34042212014-11-18 22:54:45 +000014#include "lldb/DataFormatters/TypeSummary.h"
Enrico Granataf5196282012-09-04 18:48:21 +000015
Dmitri Gribenko024aa852013-01-30 15:05:59 +000016#include "llvm/Support/ConvertUTF.h"
Enrico Granataf5196282012-09-04 18:48:21 +000017
Enrico Granatab2698cd2012-09-13 18:27:09 +000018#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/Error.h"
Enrico Granataf5196282012-09-04 18:48:21 +000020#include "lldb/Core/Stream.h"
21#include "lldb/Core/ValueObject.h"
Enrico Granatab2698cd2012-09-13 18:27:09 +000022#include "lldb/Core/ValueObjectConstResult.h"
23#include "lldb/Host/Endian.h"
Enrico Granatab5887262012-10-29 21:18:03 +000024#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataff0f23d2014-12-10 02:00:45 +000025#include "lldb/Target/SectionLoadList.h"
Enrico Granataf5196282012-09-04 18:48:21 +000026#include "lldb/Target/Target.h"
Enrico Granataba8eb122014-07-30 21:07:50 +000027#include "lldb/Target/Thread.h"
Enrico Granataf5196282012-09-04 18:48:21 +000028
Enrico Granata76b08d52014-10-29 23:08:02 +000029#include "lldb/Utility/ProcessStructReader.h"
30
Enrico Granatad83bfce2013-04-02 21:25:34 +000031#include <algorithm>
Shawn Best8da0bf32014-11-08 01:41:49 +000032#if __ANDROID_NDK__
33#include <sys/types.h>
34#endif
Enrico Granatad83bfce2013-04-02 21:25:34 +000035
Enrico Granataf5196282012-09-04 18:48:21 +000036using namespace lldb;
37using namespace lldb_private;
38using namespace lldb_private::formatters;
39
Enrico Granataba8eb122014-07-30 21:07:50 +000040StackFrame*
41lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
42{
43 StackFrame* frame = exe_ctx.GetFramePtr();
44 if (frame)
45 return frame;
46
47 Process* process = exe_ctx.GetProcessPtr();
48 if (!process)
49 return nullptr;
50
51 ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
52 if (thread_sp)
53 return thread_sp->GetSelectedFrame().get();
54 return nullptr;
55}
56
Enrico Granataf5196282012-09-04 18:48:21 +000057bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000058lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
59 const char* target_type,
60 const char* selector,
61 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000062{
63 if (!target_type || !*target_type)
64 return false;
65 if (!selector || !*selector)
66 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000067 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000068 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000069 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
70 lldb::ValueObjectSP result_sp;
71 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +000072 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf5196282012-09-04 18:48:21 +000073 if (!target || !stack_frame)
74 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000075
Jim Ingham35e1bda2012-10-16 21:41:58 +000076 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000077 options.SetCoerceToId(false);
78 options.SetUnwindOnError(true);
79 options.SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000080
Enrico Granataf5196282012-09-04 18:48:21 +000081 target->EvaluateExpression(expr.GetData(),
82 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000083 result_sp,
84 options);
Enrico Granataf5196282012-09-04 18:48:21 +000085 if (!result_sp)
86 return false;
87 value = result_sp->GetValueAsUnsigned(0);
88 return true;
89}
90
Enrico Granataf615b802013-02-15 23:38:37 +000091bool
92lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
93 const char* target_type,
94 const char* selector,
95 Stream &stream)
96{
97 if (!target_type || !*target_type)
98 return false;
99 if (!selector || !*selector)
100 return false;
101 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +0000102 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +0000103 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
104 lldb::ValueObjectSP result_sp;
105 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000106 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf615b802013-02-15 23:38:37 +0000107 if (!target || !stack_frame)
108 return false;
109
110 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000111 options.SetCoerceToId(false);
112 options.SetUnwindOnError(true);
113 options.SetKeepInMemory(true);
114 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataf615b802013-02-15 23:38:37 +0000115
116 target->EvaluateExpression(expr.GetData(),
117 stack_frame,
118 result_sp,
119 options);
120 if (!result_sp)
121 return false;
122 stream.Printf("%s",result_sp->GetSummaryAsCString());
123 return true;
124}
125
Enrico Granatab2698cd2012-09-13 18:27:09 +0000126lldb::ValueObjectSP
127lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
128 const char* return_type,
129 const char* selector,
130 uint64_t index)
131{
132 lldb::ValueObjectSP valobj_sp;
133 if (!return_type || !*return_type)
134 return valobj_sp;
135 if (!selector || !*selector)
136 return valobj_sp;
137 StreamString expr_path_stream;
138 valobj.GetExpressionPath(expr_path_stream, false);
139 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000140 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000141 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
142 lldb::ValueObjectSP result_sp;
143 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000144 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000145 if (!target || !stack_frame)
146 return valobj_sp;
147
Jim Ingham35e1bda2012-10-16 21:41:58 +0000148 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000149 options.SetCoerceToId(false);
150 options.SetUnwindOnError(true);
151 options.SetKeepInMemory(true);
152 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000153
154 target->EvaluateExpression(expr.GetData(),
155 stack_frame,
156 valobj_sp,
157 options);
158 return valobj_sp;
159}
160
161lldb::ValueObjectSP
162lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
163 const char* return_type,
164 const char* selector,
165 const char* key)
166{
167 lldb::ValueObjectSP valobj_sp;
168 if (!return_type || !*return_type)
169 return valobj_sp;
170 if (!selector || !*selector)
171 return valobj_sp;
172 if (!key || !*key)
173 return valobj_sp;
174 StreamString expr_path_stream;
175 valobj.GetExpressionPath(expr_path_stream, false);
176 StreamString expr;
177 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
178 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
179 lldb::ValueObjectSP result_sp;
180 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000181 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000182 if (!target || !stack_frame)
183 return valobj_sp;
184
Jim Ingham35e1bda2012-10-16 21:41:58 +0000185 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000186 options.SetCoerceToId(false);
187 options.SetUnwindOnError(true);
188 options.SetKeepInMemory(true);
189 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000190
191 target->EvaluateExpression(expr.GetData(),
192 stack_frame,
193 valobj_sp,
194 options);
195 return valobj_sp;
196}
197
Enrico Granataf68df122013-01-10 22:08:35 +0000198bool
Enrico Granataff0f23d2014-12-10 02:00:45 +0000199lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
200{
201 std::string destination;
202 StreamString sstr;
203 AddressType func_ptr_address_type = eAddressTypeInvalid;
204 addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type);
205 if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
206 {
207 switch (func_ptr_address_type)
208 {
209 case eAddressTypeInvalid:
210 case eAddressTypeFile:
211 case eAddressTypeHost:
212 break;
213
214 case eAddressTypeLoad:
215 {
216 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
217
218 Address so_addr;
219 Target *target = exe_ctx.GetTargetPtr();
220 if (target && target->GetSectionLoadList().IsEmpty() == false)
221 {
222 if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
223 {
224 so_addr.Dump (&sstr,
225 exe_ctx.GetBestExecutionContextScope(),
226 Address::DumpStyleResolvedDescription,
227 Address::DumpStyleSectionNameOffset);
228 }
229 }
230 }
231 break;
232 }
233 }
234 if (sstr.GetSize() > 0)
235 {
236 stream.Printf("(%s)", sstr.GetData());
237 return true;
238 }
239 else
240 return false;
241}
242
243bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000244lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000245{
246 ProcessSP process_sp = valobj.GetProcessSP();
247 if (!process_sp)
248 return false;
249
250 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
251
252 if (!valobj_addr)
253 return false;
254
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000255 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000256 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000257 options.SetProcessSP(process_sp);
258 options.SetStream(&stream);
259 options.SetPrefixToken('u');
260
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000261 if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000262 {
263 stream.Printf("Summary Unavailable");
264 return true;
265 }
266
267 return true;
268}
269
270bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000271lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000272{
273 ProcessSP process_sp = valobj.GetProcessSP();
274 if (!process_sp)
275 return false;
276
277 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
278
279 if (!valobj_addr)
280 return false;
281
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000282 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000283 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000284 options.SetProcessSP(process_sp);
285 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000286 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000287
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000288 if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000289 {
290 stream.Printf("Summary Unavailable");
291 return true;
292 }
293
294 return true;
295}
296
297bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000298lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000299{
Enrico Granata38352042013-01-11 02:44:00 +0000300 ProcessSP process_sp = valobj.GetProcessSP();
301 if (!process_sp)
302 return false;
303
Enrico Granata3309d882013-01-12 01:00:22 +0000304 lldb::addr_t data_addr = 0;
305
306 if (valobj.IsPointerType())
307 data_addr = valobj.GetValueAsUnsigned(0);
308 else if (valobj.IsArrayType())
309 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000310
Enrico Granata3309d882013-01-12 01:00:22 +0000311 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000312 return false;
313
Greg Clayton57ee3062013-07-11 22:46:58 +0000314 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
315
Enrico Granata38352042013-01-11 02:44:00 +0000316 if (!ast)
317 return false;
318
Greg Clayton57ee3062013-07-11 22:46:58 +0000319 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
320 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata38352042013-01-11 02:44:00 +0000321
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000322 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000323 options.SetLocation(data_addr);
324 options.SetProcessSP(process_sp);
325 options.SetStream(&stream);
326 options.SetPrefixToken('L');
327
Enrico Granata38352042013-01-11 02:44:00 +0000328 switch (wchar_size)
329 {
330 case 8:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000331 return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000332 case 16:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000333 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000334 case 32:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000335 return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000336 default:
337 stream.Printf("size for wchar_t is not valid");
338 return true;
339 }
340 return true;
341}
342
343bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000344lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000345{
346 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000347 Error error;
348 valobj.GetData(data, error);
349
350 if (error.Fail())
351 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000352
353 std::string value;
354 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
355 if (!value.empty())
356 stream.Printf("%s ", value.c_str());
357
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000358 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000359 options.SetData(data);
360 options.SetStream(&stream);
361 options.SetPrefixToken('u');
362 options.SetQuote('\'');
363 options.SetSourceSize(1);
364
365 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000366}
367
368bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000369lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000370{
371 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000372 Error error;
373 valobj.GetData(data, error);
374
375 if (error.Fail())
376 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000377
378 std::string value;
379 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
380 if (!value.empty())
381 stream.Printf("%s ", value.c_str());
382
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000383 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000384 options.SetData(data);
385 options.SetStream(&stream);
386 options.SetPrefixToken('U');
387 options.SetQuote('\'');
388 options.SetSourceSize(1);
389
390 return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000391}
392
393bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000394lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000395{
396 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000397 Error error;
398 valobj.GetData(data, error);
399
400 if (error.Fail())
401 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000402
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000403 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000404 options.SetData(data);
405 options.SetStream(&stream);
406 options.SetPrefixToken('L');
407 options.SetQuote('\'');
408 options.SetSourceSize(1);
Enrico Granata93d59662013-01-14 23:53:26 +0000409
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000410 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granataf68df122013-01-10 22:08:35 +0000411}
412
Enrico Granataa3962a72013-05-15 00:47:46 +0000413// the field layout in a libc++ string (cap, side, data or data, size, cap)
414enum LibcxxStringLayoutMode
415{
416 eLibcxxStringLayoutModeCSD = 0,
417 eLibcxxStringLayoutModeDSC = 1,
418 eLibcxxStringLayoutModeInvalid = 0xffff
419};
420
421// this function abstracts away the layout and mode details of a libc++ string
422// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000423static bool
424ExtractLibcxxStringInfo (ValueObject& valobj,
425 ValueObjectSP &location_sp,
426 uint64_t& size)
427{
428 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
429 if (!D)
430 return false;
431
Enrico Granataa3962a72013-05-15 00:47:46 +0000432 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
433
434 // this child should exist
435 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000436 return false;
437
Enrico Granataa3962a72013-05-15 00:47:46 +0000438 ConstString g_data_name("__data_");
439 ConstString g_size_name("__size_");
440 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
441 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
442 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000443
Enrico Granataa3962a72013-05-15 00:47:46 +0000444 if (layout == eLibcxxStringLayoutModeDSC)
445 {
446 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
447 if (!size_mode)
448 return false;
449
450 if (size_mode->GetName() != g_size_name)
451 {
452 // we are hitting the padding structure, move along
453 size_mode = D->GetChildAtIndexPath({1,1,1});
454 if (!size_mode)
455 return false;
456 }
457
458 size_mode_value = (size_mode->GetValueAsUnsigned(0));
459 short_mode = ((size_mode_value & 0x80) == 0);
460 }
461 else
462 {
463 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
464 if (!size_mode)
465 return false;
466
467 size_mode_value = (size_mode->GetValueAsUnsigned(0));
468 short_mode = ((size_mode_value & 1) == 0);
469 }
470
471 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000472 {
473 ValueObjectSP s(D->GetChildAtIndex(1, true));
474 if (!s)
475 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000476 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
477 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000478 return (location_sp.get() != nullptr);
479 }
480 else
481 {
482 ValueObjectSP l(D->GetChildAtIndex(0, true));
483 if (!l)
484 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000485 // we can use the layout_decider object as the data pointer
486 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000487 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
488 if (!size_vo || !location_sp)
489 return false;
490 size = size_vo->GetValueAsUnsigned(0);
491 return true;
492 }
493}
494
495bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000496lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata3309d882013-01-12 01:00:22 +0000497{
498 uint64_t size = 0;
499 ValueObjectSP location_sp((ValueObject*)nullptr);
500 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
501 return false;
502 if (size == 0)
503 {
504 stream.Printf("L\"\"");
505 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000506 }
Enrico Granata3309d882013-01-12 01:00:22 +0000507 if (!location_sp)
508 return false;
Enrico Granataf35bc632014-11-06 21:55:30 +0000509 return WCharStringSummaryProvider(*location_sp.get(), stream, options);
Enrico Granata3309d882013-01-12 01:00:22 +0000510}
511
512bool
Enrico Granata34042212014-11-18 22:54:45 +0000513lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000514{
515 uint64_t size = 0;
516 ValueObjectSP location_sp((ValueObject*)nullptr);
Enrico Granata2206b482014-10-30 18:27:31 +0000517
Enrico Granata3309d882013-01-12 01:00:22 +0000518 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
519 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000520
Enrico Granata3309d882013-01-12 01:00:22 +0000521 if (size == 0)
522 {
523 stream.Printf("\"\"");
524 return true;
525 }
Enrico Granata2206b482014-10-30 18:27:31 +0000526
Enrico Granata3309d882013-01-12 01:00:22 +0000527 if (!location_sp)
528 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000529
530 DataExtractor extractor;
Enrico Granata34042212014-11-18 22:54:45 +0000531 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
532 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
Enrico Granata2206b482014-10-30 18:27:31 +0000533 location_sp->GetPointeeData(extractor, 0, size);
534
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000535 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granata2206b482014-10-30 18:27:31 +0000536 options.SetData(extractor); // none of this matters for a string - pass some defaults
537 options.SetStream(&stream);
538 options.SetPrefixToken(0);
539 options.SetQuote('"');
540 options.SetSourceSize(size);
Enrico Granata2206b482014-10-30 18:27:31 +0000541 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
542
543 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000544}
545
Enrico Granata55900862013-03-15 18:55:30 +0000546bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000547lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata55900862013-03-15 18:55:30 +0000548{
549 ProcessSP process_sp = valobj.GetProcessSP();
550 if (!process_sp)
551 return false;
552
553 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
554
555 if (!runtime)
556 return false;
557
Greg Clayton03da4cc2013-04-19 21:31:16 +0000558 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000559
560 if (!descriptor.get() || !descriptor->IsValid())
561 return false;
562
563 const char* class_name = descriptor->GetClassName().GetCString();
564
565 if (!class_name || !*class_name)
566 return false;
567
568 stream.Printf("%s",class_name);
569 return true;
570}
571
Enrico Granatac76b97b2013-04-26 00:59:02 +0000572class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
573{
574public:
575 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
576 SyntheticChildrenFrontEnd(*valobj_sp.get())
577 {
578 }
579
580 virtual size_t
581 CalculateNumChildren ()
582 {
583 return 0;
584 }
585
586 virtual lldb::ValueObjectSP
587 GetChildAtIndex (size_t idx)
588 {
589 return lldb::ValueObjectSP();
590 }
591
592 virtual bool
593 Update()
594 {
595 return false;
596 }
597
598 virtual bool
599 MightHaveChildren ()
600 {
601 return false;
602 }
603
604 virtual size_t
605 GetIndexOfChildWithName (const ConstString &name)
606 {
607 return UINT32_MAX;
608 }
609
610 virtual
611 ~ObjCClassSyntheticChildrenFrontEnd ()
612 {
613 }
614};
615
616SyntheticChildrenFrontEnd*
617lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
618{
619 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
620}
621
Enrico Granataf5196282012-09-04 18:48:21 +0000622template<bool needs_at>
623bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000624lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf5196282012-09-04 18:48:21 +0000625{
626 ProcessSP process_sp = valobj.GetProcessSP();
627 if (!process_sp)
628 return false;
629
630 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
631
632 if (!runtime)
633 return false;
634
635 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
636
637 if (!descriptor.get() || !descriptor->IsValid())
638 return false;
639
640 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
641 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
642
643 if (!valobj_addr)
644 return false;
645
646 uint64_t value = 0;
647
648 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000649
650 if (!class_name || !*class_name)
651 return false;
652
Enrico Granataf5196282012-09-04 18:48:21 +0000653 if (!strcmp(class_name,"NSConcreteData") ||
654 !strcmp(class_name,"NSConcreteMutableData") ||
655 !strcmp(class_name,"__NSCFData"))
656 {
657 uint32_t offset = (is_64bit ? 16 : 8);
658 Error error;
659 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
660 if (error.Fail())
661 return false;
662 }
663 else
664 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000665 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000666 return false;
667 }
668
Daniel Malead01b2952012-11-29 21:49:15 +0000669 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000670 (needs_at ? "@\"" : ""),
671 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000672 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000673 (needs_at ? "\"" : ""));
674
675 return true;
676}
677
Enrico Granata87f00b42013-02-21 20:31:18 +0000678static bool
679ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
680 lldb::ProcessSP& process_sp,
681 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000682 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000683 Error* error = NULL,
684 size_t *data_read = NULL,
685 char prefix_token = '@',
686 char quote = '"')
687{
688 Error my_error;
689 size_t my_data_read;
690 if (!process_sp || location == 0)
691 return false;
692
Enrico Granata23ab35a2013-04-02 23:07:55 +0000693 if (!size)
694 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
695 else
696 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000697
698 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
699
700 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
701
702 if (error)
703 *error = my_error;
704 if (data_read)
705 *data_read = my_data_read;
706
707 if (my_error.Fail())
708 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000709
710 dest.Printf("%c%c",prefix_token,quote);
711
Enrico Granata87f00b42013-02-21 20:31:18 +0000712 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000713 dest.Printf("%s",(char*)buffer_sp->GetBytes());
714
715 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000716
717 return true;
718}
719
Enrico Granataf5196282012-09-04 18:48:21 +0000720bool
Jason Molenda705b1802014-06-13 02:37:02 +0000721lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
722{
723 if (!descriptor)
724 return false;
725 uint64_t len_bits = 0, data_bits = 0;
726 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
727 return false;
728
729 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
730 static const int g_SixbitMaxLen = 9;
731 static const int g_fiveBitMaxLen = 11;
732
733 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
734
735 if (len_bits > g_fiveBitMaxLen)
736 return false;
737
738 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
739 // this works under a few assumptions:
740 // little endian architecture
741 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
742 if (len_bits <= g_MaxNonBitmaskedLen)
743 {
744 stream.Printf("@\"%s\"",(const char*)&data_bits);
745 return true;
746 }
747
748 // if the data is bitmasked, we need to actually process the bytes
749 uint8_t bitmask = 0;
750 uint8_t shift_offset = 0;
751
752 if (len_bits <= g_SixbitMaxLen)
753 {
754 bitmask = 0x03f;
755 shift_offset = 6;
756 }
757 else
758 {
759 bitmask = 0x01f;
760 shift_offset = 5;
761 }
762
763 std::vector<uint8_t> bytes;
764 bytes.resize(len_bits);
765 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
766 {
767 uint8_t packed = data_bits & bitmask;
768 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
769 }
770
771 stream.Printf("@\"%s\"",&bytes[0]);
772 return true;
773}
774
Enrico Granata76b08d52014-10-29 23:08:02 +0000775static ClangASTType
776GetNSPathStore2Type (Target &target)
777{
778 static ConstString g_type_name("__lldb_autogen_nspathstore2");
779
780 ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
781
782 if (!ast_ctx)
783 return ClangASTType();
784
785 ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
786 ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
787
788 return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
789 {"isa",voidstar},
790 {"lengthAndRef",uint32},
791 {"buffer",voidstar}
792 });
793}
794
Jason Molenda705b1802014-06-13 02:37:02 +0000795bool
Enrico Granata34042212014-11-18 22:54:45 +0000796lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granataf5196282012-09-04 18:48:21 +0000797{
798 ProcessSP process_sp = valobj.GetProcessSP();
799 if (!process_sp)
800 return false;
801
802 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
803
804 if (!runtime)
805 return false;
806
807 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
808
809 if (!descriptor.get() || !descriptor->IsValid())
810 return false;
811
812 uint32_t ptr_size = process_sp->GetAddressByteSize();
813
814 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
815
816 if (!valobj_addr)
817 return false;
818
819 const char* class_name = descriptor->GetClassName().GetCString();
820
Enrico Granata60b81df2012-09-29 00:45:53 +0000821 if (!class_name || !*class_name)
822 return false;
823
Jason Molenda705b1802014-06-13 02:37:02 +0000824 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
825 // for a tagged pointer, the descriptor has everything we need
826 if (is_tagged_ptr)
827 return NSTaggedString_SummaryProvider(descriptor, stream);
828
829 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +0000830 uint64_t info_bits_location = valobj_addr + ptr_size;
831 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
832 info_bits_location += 3;
833
Enrico Granata87f00b42013-02-21 20:31:18 +0000834 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000835
836 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
837 if (error.Fail())
838 return false;
839
840 bool is_mutable = (info_bits & 1) == 1;
841 bool is_inline = (info_bits & 0x60) == 0;
842 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
843 bool is_unicode = (info_bits & 0x10) == 0x10;
844 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000845 bool has_null = (info_bits & 8) == 8;
846
847 size_t explicit_length = 0;
848 if (!has_null && has_explicit_length && !is_special)
849 {
850 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000851 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000852 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
853 else if (is_inline)
854 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000855 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000856 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
857 else
858 explicit_length_offset = 0;
859
860 if (explicit_length_offset)
861 {
862 explicit_length_offset = valobj_addr + explicit_length_offset;
863 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
864 }
865 }
866
Enrico Granataf5196282012-09-04 18:48:21 +0000867 if (strcmp(class_name,"NSString") &&
868 strcmp(class_name,"CFStringRef") &&
869 strcmp(class_name,"CFMutableStringRef") &&
870 strcmp(class_name,"__NSCFConstantString") &&
871 strcmp(class_name,"__NSCFString") &&
872 strcmp(class_name,"NSCFConstantString") &&
873 strcmp(class_name,"NSCFString") &&
874 strcmp(class_name,"NSPathStore2"))
875 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000876 // not one of us - but tell me class name
877 stream.Printf("class name = %s",class_name);
878 return true;
Enrico Granataf5196282012-09-04 18:48:21 +0000879 }
880
881 if (is_mutable)
882 {
883 uint64_t location = 2 * ptr_size + valobj_addr;
884 location = process_sp->ReadPointerFromMemory(location, error);
885 if (error.Fail())
886 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000887 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +0000888 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000889 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000890 options.SetLocation(location);
891 options.SetProcessSP(process_sp);
892 options.SetStream(&stream);
893 options.SetPrefixToken('@');
894 options.SetQuote('"');
895 options.SetSourceSize(explicit_length);
896 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000897 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000898 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata56768392013-04-23 20:05:05 +0000899 }
Enrico Granataf5196282012-09-04 18:48:21 +0000900 else
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000901 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000902 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000903 options.SetLocation(location+1);
904 options.SetProcessSP(process_sp);
905 options.SetStream(&stream);
906 options.SetPrefixToken('@');
907 options.SetSourceSize(explicit_length);
908 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000909 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000910 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
911 }
Enrico Granataf5196282012-09-04 18:48:21 +0000912 }
913 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
914 {
915 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000916 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +0000917 }
918 else if (is_unicode)
919 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000920 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000921 if (is_inline)
922 {
923 if (!has_explicit_length)
924 {
925 stream.Printf("found new combo");
926 return true;
927 }
928 else
929 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +0000930 }
Enrico Granataf5196282012-09-04 18:48:21 +0000931 else
932 {
933 location = process_sp->ReadPointerFromMemory(location, error);
934 if (error.Fail())
935 return false;
936 }
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000937 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000938 options.SetLocation(location);
939 options.SetProcessSP(process_sp);
940 options.SetStream(&stream);
941 options.SetPrefixToken('@');
942 options.SetQuote('"');
943 options.SetSourceSize(explicit_length);
944 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000945 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000946 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000947 }
948 else if (is_special)
949 {
Enrico Granata76b08d52014-10-29 23:08:02 +0000950 ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
951 explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
952 lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
953
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000954 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000955 options.SetLocation(location);
956 options.SetProcessSP(process_sp);
957 options.SetStream(&stream);
958 options.SetPrefixToken('@');
959 options.SetQuote('"');
960 options.SetSourceSize(explicit_length);
961 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000962 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000963 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000964 }
965 else if (is_inline)
966 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000967 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000968 if (!has_explicit_length)
969 location++;
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000970 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000971 options.SetLocation(location);
972 options.SetProcessSP(process_sp);
973 options.SetStream(&stream);
974 options.SetPrefixToken('@');
975 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000976 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000977 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000978 }
979 else
980 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000981 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000982 location = process_sp->ReadPointerFromMemory(location, error);
983 if (error.Fail())
984 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +0000985 if (has_explicit_length && !has_null)
986 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 +0000987 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000988 options.SetLocation(location);
989 options.SetProcessSP(process_sp);
990 options.SetPrefixToken('@');
991 options.SetStream(&stream);
992 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000993 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000994 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000995 }
Enrico Granataf5196282012-09-04 18:48:21 +0000996}
997
Enrico Granataf175ad12012-10-03 23:53:45 +0000998bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000999lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001000{
1001 TargetSP target_sp(valobj.GetTargetSP());
1002 if (!target_sp)
1003 return false;
1004 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001005 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1006 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001007 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001008 pointer_value += addr_size;
1009 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001010 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001011 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001012 if (!child_ptr_sp)
1013 return false;
1014 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001015 Error error;
1016 child_ptr_sp->GetData(data, error);
1017 if (error.Fail())
1018 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001019 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1020 child_sp->GetValueAsUnsigned(0);
1021 if (child_sp)
Enrico Granataf35bc632014-11-06 21:55:30 +00001022 return NSStringSummaryProvider(*child_sp, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001023 return false;
1024}
1025
1026bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001027lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +00001028{
Enrico Granataf35bc632014-11-06 21:55:30 +00001029 return NSAttributedStringSummaryProvider(valobj, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +00001030}
1031
1032bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001033lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf175ad12012-10-03 23:53:45 +00001034{
1035 stream.Printf("%s",valobj.GetObjectDescription());
1036 return true;
1037}
1038
Enrico Granatab5887262012-10-29 21:18:03 +00001039bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001040lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001041{
Greg Clayton57ee3062013-07-11 22:46:58 +00001042 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001043
1044 ValueObjectSP real_guy_sp = valobj.GetSP();
1045
Enrico Granata622be232014-10-21 20:52:14 +00001046 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001047 {
1048 Error err;
1049 real_guy_sp = valobj.Dereference(err);
1050 if (err.Fail() || !real_guy_sp)
1051 return false;
1052 }
Enrico Granata622be232014-10-21 20:52:14 +00001053 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001054 {
1055 real_guy_sp = valobj.GetChildAtIndex(0, true);
1056 if (!real_guy_sp)
1057 return false;
1058 }
1059 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1060 if (value == 0)
1061 {
1062 stream.Printf("NO");
1063 return true;
1064 }
1065 stream.Printf("YES");
1066 return true;
1067}
1068
1069template <bool is_sel_ptr>
1070bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001071lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001072{
Enrico Granata75dfb432013-02-15 00:06:04 +00001073 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001074
Greg Clayton57ee3062013-07-11 22:46:58 +00001075 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1076
1077 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001078 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001079
Enrico Granatab5887262012-10-29 21:18:03 +00001080 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1081
Enrico Granata75dfb432013-02-15 00:06:04 +00001082 if (is_sel_ptr)
1083 {
1084 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1085 if (data_address == LLDB_INVALID_ADDRESS)
1086 return false;
1087 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1088 }
1089 else
1090 {
1091 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001092 Error error;
1093 valobj.GetData(data, error);
1094 if (error.Fail())
1095 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001096 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1097 }
Enrico Granatab5887262012-10-29 21:18:03 +00001098
Enrico Granata75dfb432013-02-15 00:06:04 +00001099 if (!valobj_sp)
1100 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001101
1102 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1103 return true;
1104}
1105
Enrico Granata6d37cc62013-03-19 00:27:22 +00001106// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1107// this call gives the POSIX equivalent of the Cocoa epoch
1108time_t
Enrico Granata92373532013-03-19 22:58:48 +00001109lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001110{
1111 static time_t epoch = 0;
1112 if (!epoch)
1113 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001114#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001115 tzset();
1116 tm tm_epoch;
1117 tm_epoch.tm_sec = 0;
1118 tm_epoch.tm_hour = 0;
1119 tm_epoch.tm_min = 0;
1120 tm_epoch.tm_mon = 0;
1121 tm_epoch.tm_mday = 1;
1122 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1123 tm_epoch.tm_isdst = -1;
1124 tm_epoch.tm_gmtoff = 0;
1125 tm_epoch.tm_zone = NULL;
1126 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001127#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001128 }
1129 return epoch;
1130}
1131
Greg Claytonc7bece562013-01-25 18:06:21 +00001132size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001133lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001134{
1135 if (!item_name || !*item_name)
1136 return UINT32_MAX;
1137 if (*item_name != '[')
1138 return UINT32_MAX;
1139 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001140 char* endptr = NULL;
1141 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1142 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001143 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001144 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001145 return UINT32_MAX;
1146 return idx;
1147}
1148
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001149lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1150 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001151SyntheticChildrenFrontEnd(*valobj_sp.get()),
1152m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001153m_item_name(item_name),
1154m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001155{
1156 if (valobj_sp)
1157 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001158}
1159
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001160bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001161lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001162{
Enrico Granata6eca3552013-03-28 18:50:54 +00001163 m_item_sp.reset();
1164
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001165 ValueObjectSP valobj_sp = m_backend.GetSP();
1166 if (!valobj_sp)
1167 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001168
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001169 if (!valobj_sp)
1170 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001171
1172 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1173 if (!item_ptr)
1174 return false;
1175 if (item_ptr->GetValueAsUnsigned(0) == 0)
1176 return false;
1177 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001178 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granatae29df232014-12-09 19:51:20 +00001179 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001180 if (err.Fail())
1181 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001182 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001183}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001184
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001185size_t
1186lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1187{
1188 return 1;
1189}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001190
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001191lldb::ValueObjectSP
1192lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1193{
1194 if (idx == 0)
1195 return m_item_sp;
1196 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001197}
1198
1199bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001200lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001201{
1202 return true;
1203}
1204
1205size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001206lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001207{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001208 if (name == ConstString("item"))
1209 return 0;
1210 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001211}
1212
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001213lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001214{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001215}
1216
Enrico Granataf5196282012-09-04 18:48:21 +00001217template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001218lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab2698cd2012-09-13 18:27:09 +00001219
1220template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001221lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001222
1223template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001224lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001225
1226template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001227lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;