blob: 90780c397bc69088f972ef77e9e901e664d39104 [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 Granataf5196282012-09-04 18:48:21 +000025#include "lldb/Target/Target.h"
Enrico Granataba8eb122014-07-30 21:07:50 +000026#include "lldb/Target/Thread.h"
Enrico Granataf5196282012-09-04 18:48:21 +000027
Enrico Granata76b08d52014-10-29 23:08:02 +000028#include "lldb/Utility/ProcessStructReader.h"
29
Enrico Granatad83bfce2013-04-02 21:25:34 +000030#include <algorithm>
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
Enrico Granataf5196282012-09-04 18:48:21 +000035using namespace lldb;
36using namespace lldb_private;
37using namespace lldb_private::formatters;
38
Enrico Granataba8eb122014-07-30 21:07:50 +000039StackFrame*
40lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
41{
42 StackFrame* frame = exe_ctx.GetFramePtr();
43 if (frame)
44 return frame;
45
46 Process* process = exe_ctx.GetProcessPtr();
47 if (!process)
48 return nullptr;
49
50 ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
51 if (thread_sp)
52 return thread_sp->GetSelectedFrame().get();
53 return nullptr;
54}
55
Enrico Granataf5196282012-09-04 18:48:21 +000056bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000057lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
58 const char* target_type,
59 const char* selector,
60 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000061{
62 if (!target_type || !*target_type)
63 return false;
64 if (!selector || !*selector)
65 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000066 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000067 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000068 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
69 lldb::ValueObjectSP result_sp;
70 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +000071 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf5196282012-09-04 18:48:21 +000072 if (!target || !stack_frame)
73 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000074
Jim Ingham35e1bda2012-10-16 21:41:58 +000075 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000076 options.SetCoerceToId(false);
77 options.SetUnwindOnError(true);
78 options.SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000079
Enrico Granataf5196282012-09-04 18:48:21 +000080 target->EvaluateExpression(expr.GetData(),
81 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000082 result_sp,
83 options);
Enrico Granataf5196282012-09-04 18:48:21 +000084 if (!result_sp)
85 return false;
86 value = result_sp->GetValueAsUnsigned(0);
87 return true;
88}
89
Enrico Granataf615b802013-02-15 23:38:37 +000090bool
91lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
92 const char* target_type,
93 const char* selector,
94 Stream &stream)
95{
96 if (!target_type || !*target_type)
97 return false;
98 if (!selector || !*selector)
99 return false;
100 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +0000101 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +0000102 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
103 lldb::ValueObjectSP result_sp;
104 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000105 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf615b802013-02-15 23:38:37 +0000106 if (!target || !stack_frame)
107 return false;
108
109 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000110 options.SetCoerceToId(false);
111 options.SetUnwindOnError(true);
112 options.SetKeepInMemory(true);
113 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataf615b802013-02-15 23:38:37 +0000114
115 target->EvaluateExpression(expr.GetData(),
116 stack_frame,
117 result_sp,
118 options);
119 if (!result_sp)
120 return false;
121 stream.Printf("%s",result_sp->GetSummaryAsCString());
122 return true;
123}
124
Enrico Granatab2698cd2012-09-13 18:27:09 +0000125lldb::ValueObjectSP
126lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
127 const char* return_type,
128 const char* selector,
129 uint64_t index)
130{
131 lldb::ValueObjectSP valobj_sp;
132 if (!return_type || !*return_type)
133 return valobj_sp;
134 if (!selector || !*selector)
135 return valobj_sp;
136 StreamString expr_path_stream;
137 valobj.GetExpressionPath(expr_path_stream, false);
138 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000139 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000140 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
141 lldb::ValueObjectSP result_sp;
142 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000143 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000144 if (!target || !stack_frame)
145 return valobj_sp;
146
Jim Ingham35e1bda2012-10-16 21:41:58 +0000147 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000148 options.SetCoerceToId(false);
149 options.SetUnwindOnError(true);
150 options.SetKeepInMemory(true);
151 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000152
153 target->EvaluateExpression(expr.GetData(),
154 stack_frame,
155 valobj_sp,
156 options);
157 return valobj_sp;
158}
159
160lldb::ValueObjectSP
161lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
162 const char* return_type,
163 const char* selector,
164 const char* key)
165{
166 lldb::ValueObjectSP valobj_sp;
167 if (!return_type || !*return_type)
168 return valobj_sp;
169 if (!selector || !*selector)
170 return valobj_sp;
171 if (!key || !*key)
172 return valobj_sp;
173 StreamString expr_path_stream;
174 valobj.GetExpressionPath(expr_path_stream, false);
175 StreamString expr;
176 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
177 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
178 lldb::ValueObjectSP result_sp;
179 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000180 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000181 if (!target || !stack_frame)
182 return valobj_sp;
183
Jim Ingham35e1bda2012-10-16 21:41:58 +0000184 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000185 options.SetCoerceToId(false);
186 options.SetUnwindOnError(true);
187 options.SetKeepInMemory(true);
188 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000189
190 target->EvaluateExpression(expr.GetData(),
191 stack_frame,
192 valobj_sp,
193 options);
194 return valobj_sp;
195}
196
Enrico Granataf68df122013-01-10 22:08:35 +0000197bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000198lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000199{
200 ProcessSP process_sp = valobj.GetProcessSP();
201 if (!process_sp)
202 return false;
203
204 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
205
206 if (!valobj_addr)
207 return false;
208
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000209 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000210 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000211 options.SetProcessSP(process_sp);
212 options.SetStream(&stream);
213 options.SetPrefixToken('u');
214
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000215 if (!ReadStringAndDumpToStream<StringElementType::UTF16>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000216 {
217 stream.Printf("Summary Unavailable");
218 return true;
219 }
220
221 return true;
222}
223
224bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000225lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000226{
227 ProcessSP process_sp = valobj.GetProcessSP();
228 if (!process_sp)
229 return false;
230
231 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
232
233 if (!valobj_addr)
234 return false;
235
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000236 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000237 options.SetLocation(valobj_addr);
Enrico Granata56768392013-04-23 20:05:05 +0000238 options.SetProcessSP(process_sp);
239 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000240 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000241
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000242 if (!ReadStringAndDumpToStream<StringElementType::UTF32>(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000243 {
244 stream.Printf("Summary Unavailable");
245 return true;
246 }
247
248 return true;
249}
250
251bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000252lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granataf68df122013-01-10 22:08:35 +0000253{
Enrico Granata38352042013-01-11 02:44:00 +0000254 ProcessSP process_sp = valobj.GetProcessSP();
255 if (!process_sp)
256 return false;
257
Enrico Granata3309d882013-01-12 01:00:22 +0000258 lldb::addr_t data_addr = 0;
259
260 if (valobj.IsPointerType())
261 data_addr = valobj.GetValueAsUnsigned(0);
262 else if (valobj.IsArrayType())
263 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000264
Enrico Granata3309d882013-01-12 01:00:22 +0000265 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000266 return false;
267
Greg Clayton57ee3062013-07-11 22:46:58 +0000268 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
269
Enrico Granata38352042013-01-11 02:44:00 +0000270 if (!ast)
271 return false;
272
Greg Clayton57ee3062013-07-11 22:46:58 +0000273 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
274 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata38352042013-01-11 02:44:00 +0000275
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000276 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000277 options.SetLocation(data_addr);
278 options.SetProcessSP(process_sp);
279 options.SetStream(&stream);
280 options.SetPrefixToken('L');
281
Enrico Granata38352042013-01-11 02:44:00 +0000282 switch (wchar_size)
283 {
284 case 8:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000285 return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000286 case 16:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000287 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata38352042013-01-11 02:44:00 +0000288 case 32:
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000289 return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000290 default:
291 stream.Printf("size for wchar_t is not valid");
292 return true;
293 }
294 return true;
295}
296
297bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000298lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000299{
300 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000301 Error error;
302 valobj.GetData(data, error);
303
304 if (error.Fail())
305 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000306
307 std::string value;
308 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
309 if (!value.empty())
310 stream.Printf("%s ", value.c_str());
311
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000312 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000313 options.SetData(data);
314 options.SetStream(&stream);
315 options.SetPrefixToken('u');
316 options.SetQuote('\'');
317 options.SetSourceSize(1);
318
319 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000320}
321
322bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000323lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000324{
325 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000326 Error error;
327 valobj.GetData(data, error);
328
329 if (error.Fail())
330 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000331
332 std::string value;
333 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
334 if (!value.empty())
335 stream.Printf("%s ", value.c_str());
336
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000337 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000338 options.SetData(data);
339 options.SetStream(&stream);
340 options.SetPrefixToken('U');
341 options.SetQuote('\'');
342 options.SetSourceSize(1);
343
344 return ReadBufferAndDumpToStream<StringElementType::UTF32>(options);
Enrico Granata93d59662013-01-14 23:53:26 +0000345}
346
347bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000348lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
Enrico Granata93d59662013-01-14 23:53:26 +0000349{
350 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000351 Error error;
352 valobj.GetData(data, error);
353
354 if (error.Fail())
355 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000356
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000357 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000358 options.SetData(data);
359 options.SetStream(&stream);
360 options.SetPrefixToken('L');
361 options.SetQuote('\'');
362 options.SetSourceSize(1);
Enrico Granata93d59662013-01-14 23:53:26 +0000363
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000364 return ReadBufferAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granataf68df122013-01-10 22:08:35 +0000365}
366
Enrico Granataa3962a72013-05-15 00:47:46 +0000367// the field layout in a libc++ string (cap, side, data or data, size, cap)
368enum LibcxxStringLayoutMode
369{
370 eLibcxxStringLayoutModeCSD = 0,
371 eLibcxxStringLayoutModeDSC = 1,
372 eLibcxxStringLayoutModeInvalid = 0xffff
373};
374
375// this function abstracts away the layout and mode details of a libc++ string
376// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000377static bool
378ExtractLibcxxStringInfo (ValueObject& valobj,
379 ValueObjectSP &location_sp,
380 uint64_t& size)
381{
382 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
383 if (!D)
384 return false;
385
Enrico Granataa3962a72013-05-15 00:47:46 +0000386 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
387
388 // this child should exist
389 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000390 return false;
391
Enrico Granataa3962a72013-05-15 00:47:46 +0000392 ConstString g_data_name("__data_");
393 ConstString g_size_name("__size_");
394 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
395 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
396 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000397
Enrico Granataa3962a72013-05-15 00:47:46 +0000398 if (layout == eLibcxxStringLayoutModeDSC)
399 {
400 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
401 if (!size_mode)
402 return false;
403
404 if (size_mode->GetName() != g_size_name)
405 {
406 // we are hitting the padding structure, move along
407 size_mode = D->GetChildAtIndexPath({1,1,1});
408 if (!size_mode)
409 return false;
410 }
411
412 size_mode_value = (size_mode->GetValueAsUnsigned(0));
413 short_mode = ((size_mode_value & 0x80) == 0);
414 }
415 else
416 {
417 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
418 if (!size_mode)
419 return false;
420
421 size_mode_value = (size_mode->GetValueAsUnsigned(0));
422 short_mode = ((size_mode_value & 1) == 0);
423 }
424
425 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000426 {
427 ValueObjectSP s(D->GetChildAtIndex(1, true));
428 if (!s)
429 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000430 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
431 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000432 return (location_sp.get() != nullptr);
433 }
434 else
435 {
436 ValueObjectSP l(D->GetChildAtIndex(0, true));
437 if (!l)
438 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000439 // we can use the layout_decider object as the data pointer
440 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000441 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
442 if (!size_vo || !location_sp)
443 return false;
444 size = size_vo->GetValueAsUnsigned(0);
445 return true;
446 }
447}
448
449bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000450lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata3309d882013-01-12 01:00:22 +0000451{
452 uint64_t size = 0;
453 ValueObjectSP location_sp((ValueObject*)nullptr);
454 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
455 return false;
456 if (size == 0)
457 {
458 stream.Printf("L\"\"");
459 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000460 }
Enrico Granata3309d882013-01-12 01:00:22 +0000461 if (!location_sp)
462 return false;
Enrico Granataf35bc632014-11-06 21:55:30 +0000463 return WCharStringSummaryProvider(*location_sp.get(), stream, options);
Enrico Granata3309d882013-01-12 01:00:22 +0000464}
465
466bool
Enrico Granata34042212014-11-18 22:54:45 +0000467lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granata3309d882013-01-12 01:00:22 +0000468{
469 uint64_t size = 0;
470 ValueObjectSP location_sp((ValueObject*)nullptr);
Enrico Granata2206b482014-10-30 18:27:31 +0000471
Enrico Granata3309d882013-01-12 01:00:22 +0000472 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
473 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000474
Enrico Granata3309d882013-01-12 01:00:22 +0000475 if (size == 0)
476 {
477 stream.Printf("\"\"");
478 return true;
479 }
Enrico Granata2206b482014-10-30 18:27:31 +0000480
Enrico Granata3309d882013-01-12 01:00:22 +0000481 if (!location_sp)
482 return false;
Enrico Granata2206b482014-10-30 18:27:31 +0000483
484 DataExtractor extractor;
Enrico Granata34042212014-11-18 22:54:45 +0000485 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
486 size = std::min<decltype(size)>(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary());
Enrico Granata2206b482014-10-30 18:27:31 +0000487 location_sp->GetPointeeData(extractor, 0, size);
488
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000489 ReadBufferAndDumpToStreamOptions options(valobj);
Enrico Granata2206b482014-10-30 18:27:31 +0000490 options.SetData(extractor); // none of this matters for a string - pass some defaults
491 options.SetStream(&stream);
492 options.SetPrefixToken(0);
493 options.SetQuote('"');
494 options.SetSourceSize(size);
Enrico Granata2206b482014-10-30 18:27:31 +0000495 lldb_private::formatters::ReadBufferAndDumpToStream<lldb_private::formatters::StringElementType::ASCII>(options);
496
497 return true;
Enrico Granata3309d882013-01-12 01:00:22 +0000498}
499
Enrico Granata55900862013-03-15 18:55:30 +0000500bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000501lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata55900862013-03-15 18:55:30 +0000502{
503 ProcessSP process_sp = valobj.GetProcessSP();
504 if (!process_sp)
505 return false;
506
507 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
508
509 if (!runtime)
510 return false;
511
Greg Clayton03da4cc2013-04-19 21:31:16 +0000512 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000513
514 if (!descriptor.get() || !descriptor->IsValid())
515 return false;
516
517 const char* class_name = descriptor->GetClassName().GetCString();
518
519 if (!class_name || !*class_name)
520 return false;
521
522 stream.Printf("%s",class_name);
523 return true;
524}
525
Enrico Granatac76b97b2013-04-26 00:59:02 +0000526class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
527{
528public:
529 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
530 SyntheticChildrenFrontEnd(*valobj_sp.get())
531 {
532 }
533
534 virtual size_t
535 CalculateNumChildren ()
536 {
537 return 0;
538 }
539
540 virtual lldb::ValueObjectSP
541 GetChildAtIndex (size_t idx)
542 {
543 return lldb::ValueObjectSP();
544 }
545
546 virtual bool
547 Update()
548 {
549 return false;
550 }
551
552 virtual bool
553 MightHaveChildren ()
554 {
555 return false;
556 }
557
558 virtual size_t
559 GetIndexOfChildWithName (const ConstString &name)
560 {
561 return UINT32_MAX;
562 }
563
564 virtual
565 ~ObjCClassSyntheticChildrenFrontEnd ()
566 {
567 }
568};
569
570SyntheticChildrenFrontEnd*
571lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
572{
573 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
574}
575
Enrico Granataf5196282012-09-04 18:48:21 +0000576template<bool needs_at>
577bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000578lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf5196282012-09-04 18:48:21 +0000579{
580 ProcessSP process_sp = valobj.GetProcessSP();
581 if (!process_sp)
582 return false;
583
584 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
585
586 if (!runtime)
587 return false;
588
589 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
590
591 if (!descriptor.get() || !descriptor->IsValid())
592 return false;
593
594 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
595 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
596
597 if (!valobj_addr)
598 return false;
599
600 uint64_t value = 0;
601
602 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000603
604 if (!class_name || !*class_name)
605 return false;
606
Enrico Granataf5196282012-09-04 18:48:21 +0000607 if (!strcmp(class_name,"NSConcreteData") ||
608 !strcmp(class_name,"NSConcreteMutableData") ||
609 !strcmp(class_name,"__NSCFData"))
610 {
611 uint32_t offset = (is_64bit ? 16 : 8);
612 Error error;
613 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
614 if (error.Fail())
615 return false;
616 }
617 else
618 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000619 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000620 return false;
621 }
622
Daniel Malead01b2952012-11-29 21:49:15 +0000623 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000624 (needs_at ? "@\"" : ""),
625 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000626 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000627 (needs_at ? "\"" : ""));
628
629 return true;
630}
631
Enrico Granata87f00b42013-02-21 20:31:18 +0000632static bool
633ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
634 lldb::ProcessSP& process_sp,
635 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000636 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000637 Error* error = NULL,
638 size_t *data_read = NULL,
639 char prefix_token = '@',
640 char quote = '"')
641{
642 Error my_error;
643 size_t my_data_read;
644 if (!process_sp || location == 0)
645 return false;
646
Enrico Granata23ab35a2013-04-02 23:07:55 +0000647 if (!size)
648 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
649 else
650 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000651
652 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
653
654 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
655
656 if (error)
657 *error = my_error;
658 if (data_read)
659 *data_read = my_data_read;
660
661 if (my_error.Fail())
662 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000663
664 dest.Printf("%c%c",prefix_token,quote);
665
Enrico Granata87f00b42013-02-21 20:31:18 +0000666 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000667 dest.Printf("%s",(char*)buffer_sp->GetBytes());
668
669 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000670
671 return true;
672}
673
Enrico Granataf5196282012-09-04 18:48:21 +0000674bool
Jason Molenda705b1802014-06-13 02:37:02 +0000675lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
676{
677 if (!descriptor)
678 return false;
679 uint64_t len_bits = 0, data_bits = 0;
680 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
681 return false;
682
683 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
684 static const int g_SixbitMaxLen = 9;
685 static const int g_fiveBitMaxLen = 11;
686
687 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
688
689 if (len_bits > g_fiveBitMaxLen)
690 return false;
691
692 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
693 // this works under a few assumptions:
694 // little endian architecture
695 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
696 if (len_bits <= g_MaxNonBitmaskedLen)
697 {
698 stream.Printf("@\"%s\"",(const char*)&data_bits);
699 return true;
700 }
701
702 // if the data is bitmasked, we need to actually process the bytes
703 uint8_t bitmask = 0;
704 uint8_t shift_offset = 0;
705
706 if (len_bits <= g_SixbitMaxLen)
707 {
708 bitmask = 0x03f;
709 shift_offset = 6;
710 }
711 else
712 {
713 bitmask = 0x01f;
714 shift_offset = 5;
715 }
716
717 std::vector<uint8_t> bytes;
718 bytes.resize(len_bits);
719 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
720 {
721 uint8_t packed = data_bits & bitmask;
722 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
723 }
724
725 stream.Printf("@\"%s\"",&bytes[0]);
726 return true;
727}
728
Enrico Granata76b08d52014-10-29 23:08:02 +0000729static ClangASTType
730GetNSPathStore2Type (Target &target)
731{
732 static ConstString g_type_name("__lldb_autogen_nspathstore2");
733
734 ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
735
736 if (!ast_ctx)
737 return ClangASTType();
738
739 ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
740 ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false);
741
742 return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
743 {"isa",voidstar},
744 {"lengthAndRef",uint32},
745 {"buffer",voidstar}
746 });
747}
748
Jason Molenda705b1802014-06-13 02:37:02 +0000749bool
Enrico Granata34042212014-11-18 22:54:45 +0000750lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
Enrico Granataf5196282012-09-04 18:48:21 +0000751{
752 ProcessSP process_sp = valobj.GetProcessSP();
753 if (!process_sp)
754 return false;
755
756 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
757
758 if (!runtime)
759 return false;
760
761 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
762
763 if (!descriptor.get() || !descriptor->IsValid())
764 return false;
765
766 uint32_t ptr_size = process_sp->GetAddressByteSize();
767
768 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
769
770 if (!valobj_addr)
771 return false;
772
773 const char* class_name = descriptor->GetClassName().GetCString();
774
Enrico Granata60b81df2012-09-29 00:45:53 +0000775 if (!class_name || !*class_name)
776 return false;
777
Jason Molenda705b1802014-06-13 02:37:02 +0000778 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
779 // for a tagged pointer, the descriptor has everything we need
780 if (is_tagged_ptr)
781 return NSTaggedString_SummaryProvider(descriptor, stream);
782
783 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +0000784 uint64_t info_bits_location = valobj_addr + ptr_size;
785 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
786 info_bits_location += 3;
787
Enrico Granata87f00b42013-02-21 20:31:18 +0000788 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000789
790 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
791 if (error.Fail())
792 return false;
793
794 bool is_mutable = (info_bits & 1) == 1;
795 bool is_inline = (info_bits & 0x60) == 0;
796 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
797 bool is_unicode = (info_bits & 0x10) == 0x10;
798 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000799 bool has_null = (info_bits & 8) == 8;
800
801 size_t explicit_length = 0;
802 if (!has_null && has_explicit_length && !is_special)
803 {
804 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000805 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000806 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
807 else if (is_inline)
808 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000809 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +0000810 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
811 else
812 explicit_length_offset = 0;
813
814 if (explicit_length_offset)
815 {
816 explicit_length_offset = valobj_addr + explicit_length_offset;
817 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
818 }
819 }
820
Enrico Granataf5196282012-09-04 18:48:21 +0000821 if (strcmp(class_name,"NSString") &&
822 strcmp(class_name,"CFStringRef") &&
823 strcmp(class_name,"CFMutableStringRef") &&
824 strcmp(class_name,"__NSCFConstantString") &&
825 strcmp(class_name,"__NSCFString") &&
826 strcmp(class_name,"NSCFConstantString") &&
827 strcmp(class_name,"NSCFString") &&
828 strcmp(class_name,"NSPathStore2"))
829 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000830 // not one of us - but tell me class name
831 stream.Printf("class name = %s",class_name);
832 return true;
Enrico Granataf5196282012-09-04 18:48:21 +0000833 }
834
835 if (is_mutable)
836 {
837 uint64_t location = 2 * ptr_size + valobj_addr;
838 location = process_sp->ReadPointerFromMemory(location, error);
839 if (error.Fail())
840 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +0000841 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +0000842 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000843 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000844 options.SetLocation(location);
845 options.SetProcessSP(process_sp);
846 options.SetStream(&stream);
847 options.SetPrefixToken('@');
848 options.SetQuote('"');
849 options.SetSourceSize(explicit_length);
850 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000851 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000852 return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
Enrico Granata56768392013-04-23 20:05:05 +0000853 }
Enrico Granataf5196282012-09-04 18:48:21 +0000854 else
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000855 {
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000856 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000857 options.SetLocation(location+1);
858 options.SetProcessSP(process_sp);
859 options.SetStream(&stream);
860 options.SetPrefixToken('@');
861 options.SetSourceSize(explicit_length);
862 options.SetNeedsZeroTermination(false);
Enrico Granata34042212014-11-18 22:54:45 +0000863 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000864 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
865 }
Enrico Granataf5196282012-09-04 18:48:21 +0000866 }
867 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
868 {
869 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000870 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +0000871 }
872 else if (is_unicode)
873 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000874 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000875 if (is_inline)
876 {
877 if (!has_explicit_length)
878 {
879 stream.Printf("found new combo");
880 return true;
881 }
882 else
883 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +0000884 }
Enrico Granataf5196282012-09-04 18:48:21 +0000885 else
886 {
887 location = process_sp->ReadPointerFromMemory(location, error);
888 if (error.Fail())
889 return false;
890 }
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(has_explicit_length == 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 Granataf5196282012-09-04 18:48:21 +0000901 }
902 else if (is_special)
903 {
Enrico Granata76b08d52014-10-29 23:08:02 +0000904 ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
905 explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
906 lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
907
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000908 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granata56768392013-04-23 20:05:05 +0000909 options.SetLocation(location);
910 options.SetProcessSP(process_sp);
911 options.SetStream(&stream);
912 options.SetPrefixToken('@');
913 options.SetQuote('"');
914 options.SetSourceSize(explicit_length);
915 options.SetNeedsZeroTermination(has_explicit_length == false);
Enrico Granata34042212014-11-18 22:54:45 +0000916 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000917 return ReadStringAndDumpToStream<StringElementType::UTF16> (options);
Enrico Granataf5196282012-09-04 18:48:21 +0000918 }
919 else if (is_inline)
920 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000921 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000922 if (!has_explicit_length)
923 location++;
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000924 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000925 options.SetLocation(location);
926 options.SetProcessSP(process_sp);
927 options.SetStream(&stream);
928 options.SetPrefixToken('@');
929 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000930 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000931 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000932 }
933 else
934 {
Enrico Granata87f00b42013-02-21 20:31:18 +0000935 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +0000936 location = process_sp->ReadPointerFromMemory(location, error);
937 if (error.Fail())
938 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +0000939 if (has_explicit_length && !has_null)
940 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 +0000941 ReadStringAndDumpToStreamOptions options(valobj);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000942 options.SetLocation(location);
943 options.SetProcessSP(process_sp);
944 options.SetPrefixToken('@');
945 options.SetStream(&stream);
946 options.SetSourceSize(explicit_length);
Enrico Granata34042212014-11-18 22:54:45 +0000947 options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000948 return ReadStringAndDumpToStream<StringElementType::ASCII>(options);
Enrico Granataf5196282012-09-04 18:48:21 +0000949 }
Enrico Granataf5196282012-09-04 18:48:21 +0000950}
951
Enrico Granataf175ad12012-10-03 23:53:45 +0000952bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000953lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +0000954{
955 TargetSP target_sp(valobj.GetTargetSP());
956 if (!target_sp)
957 return false;
958 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +0000959 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
960 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +0000961 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +0000962 pointer_value += addr_size;
963 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +0000964 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +0000965 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +0000966 if (!child_ptr_sp)
967 return false;
968 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000969 Error error;
970 child_ptr_sp->GetData(data, error);
971 if (error.Fail())
972 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +0000973 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
974 child_sp->GetValueAsUnsigned(0);
975 if (child_sp)
Enrico Granataf35bc632014-11-06 21:55:30 +0000976 return NSStringSummaryProvider(*child_sp, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +0000977 return false;
978}
979
980bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000981lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granata5bfce362013-02-08 01:55:46 +0000982{
Enrico Granataf35bc632014-11-06 21:55:30 +0000983 return NSAttributedStringSummaryProvider(valobj, stream, options);
Enrico Granata5bfce362013-02-08 01:55:46 +0000984}
985
986bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000987lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granataf175ad12012-10-03 23:53:45 +0000988{
989 stream.Printf("%s",valobj.GetObjectDescription());
990 return true;
991}
992
Enrico Granatab5887262012-10-29 21:18:03 +0000993bool
Enrico Granataf35bc632014-11-06 21:55:30 +0000994lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +0000995{
Greg Clayton57ee3062013-07-11 22:46:58 +0000996 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +0000997
998 ValueObjectSP real_guy_sp = valobj.GetSP();
999
Enrico Granata622be232014-10-21 20:52:14 +00001000 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001001 {
1002 Error err;
1003 real_guy_sp = valobj.Dereference(err);
1004 if (err.Fail() || !real_guy_sp)
1005 return false;
1006 }
Enrico Granata622be232014-10-21 20:52:14 +00001007 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001008 {
1009 real_guy_sp = valobj.GetChildAtIndex(0, true);
1010 if (!real_guy_sp)
1011 return false;
1012 }
1013 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1014 if (value == 0)
1015 {
1016 stream.Printf("NO");
1017 return true;
1018 }
1019 stream.Printf("YES");
1020 return true;
1021}
1022
1023template <bool is_sel_ptr>
1024bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001025lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
Enrico Granatab5887262012-10-29 21:18:03 +00001026{
Enrico Granata75dfb432013-02-15 00:06:04 +00001027 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001028
Greg Clayton57ee3062013-07-11 22:46:58 +00001029 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1030
1031 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001032 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001033
Enrico Granatab5887262012-10-29 21:18:03 +00001034 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1035
Enrico Granata75dfb432013-02-15 00:06:04 +00001036 if (is_sel_ptr)
1037 {
1038 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1039 if (data_address == LLDB_INVALID_ADDRESS)
1040 return false;
1041 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1042 }
1043 else
1044 {
1045 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001046 Error error;
1047 valobj.GetData(data, error);
1048 if (error.Fail())
1049 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001050 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1051 }
Enrico Granatab5887262012-10-29 21:18:03 +00001052
Enrico Granata75dfb432013-02-15 00:06:04 +00001053 if (!valobj_sp)
1054 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001055
1056 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1057 return true;
1058}
1059
Enrico Granata6d37cc62013-03-19 00:27:22 +00001060// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1061// this call gives the POSIX equivalent of the Cocoa epoch
1062time_t
Enrico Granata92373532013-03-19 22:58:48 +00001063lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001064{
1065 static time_t epoch = 0;
1066 if (!epoch)
1067 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001068#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001069 tzset();
1070 tm tm_epoch;
1071 tm_epoch.tm_sec = 0;
1072 tm_epoch.tm_hour = 0;
1073 tm_epoch.tm_min = 0;
1074 tm_epoch.tm_mon = 0;
1075 tm_epoch.tm_mday = 1;
1076 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1077 tm_epoch.tm_isdst = -1;
1078 tm_epoch.tm_gmtoff = 0;
1079 tm_epoch.tm_zone = NULL;
1080 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001081#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001082 }
1083 return epoch;
1084}
1085
Greg Claytonc7bece562013-01-25 18:06:21 +00001086size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001087lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001088{
1089 if (!item_name || !*item_name)
1090 return UINT32_MAX;
1091 if (*item_name != '[')
1092 return UINT32_MAX;
1093 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001094 char* endptr = NULL;
1095 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1096 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001097 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001098 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001099 return UINT32_MAX;
1100 return idx;
1101}
1102
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001103lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1104 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001105SyntheticChildrenFrontEnd(*valobj_sp.get()),
1106m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001107m_item_name(item_name),
1108m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001109{
1110 if (valobj_sp)
1111 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001112}
1113
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001114bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001115lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001116{
Enrico Granata6eca3552013-03-28 18:50:54 +00001117 m_item_sp.reset();
1118
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001119 ValueObjectSP valobj_sp = m_backend.GetSP();
1120 if (!valobj_sp)
1121 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001122
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001123 if (!valobj_sp)
1124 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001125
1126 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1127 if (!item_ptr)
1128 return false;
1129 if (item_ptr->GetValueAsUnsigned(0) == 0)
1130 return false;
1131 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001132 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granatae29df232014-12-09 19:51:20 +00001133 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001134 if (err.Fail())
1135 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001136 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001137}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001138
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001139size_t
1140lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1141{
1142 return 1;
1143}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001144
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001145lldb::ValueObjectSP
1146lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1147{
1148 if (idx == 0)
1149 return m_item_sp;
1150 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001151}
1152
1153bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001154lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001155{
1156 return true;
1157}
1158
1159size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001160lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001161{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001162 if (name == ConstString("item"))
1163 return 0;
1164 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001165}
1166
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001167lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001168{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001169}
1170
Enrico Granataf5196282012-09-04 18:48:21 +00001171template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001172lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab2698cd2012-09-13 18:27:09 +00001173
1174template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001175lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001176
1177template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001178lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001179
1180template bool
Enrico Granataf35bc632014-11-06 21:55:30 +00001181lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;