blob: c8e5055d49fa1dc2414ec854ca1b02899dd2018c [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 Granataf5196282012-09-04 18:48:21 +000013
Dmitri Gribenko024aa852013-01-30 15:05:59 +000014#include "llvm/Support/ConvertUTF.h"
Enrico Granataf5196282012-09-04 18:48:21 +000015
Enrico Granatab2698cd2012-09-13 18:27:09 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/Error.h"
Enrico Granataf5196282012-09-04 18:48:21 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/ValueObject.h"
Enrico Granatab2698cd2012-09-13 18:27:09 +000020#include "lldb/Core/ValueObjectConstResult.h"
21#include "lldb/Host/Endian.h"
Enrico Granatab5887262012-10-29 21:18:03 +000022#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataf5196282012-09-04 18:48:21 +000023#include "lldb/Target/Target.h"
Enrico Granataba8eb122014-07-30 21:07:50 +000024#include "lldb/Target/Thread.h"
Enrico Granataf5196282012-09-04 18:48:21 +000025
Enrico Granatad83bfce2013-04-02 21:25:34 +000026#include <algorithm>
27
Enrico Granataf5196282012-09-04 18:48:21 +000028using namespace lldb;
29using namespace lldb_private;
30using namespace lldb_private::formatters;
31
Enrico Granataba8eb122014-07-30 21:07:50 +000032StackFrame*
33lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx)
34{
35 StackFrame* frame = exe_ctx.GetFramePtr();
36 if (frame)
37 return frame;
38
39 Process* process = exe_ctx.GetProcessPtr();
40 if (!process)
41 return nullptr;
42
43 ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
44 if (thread_sp)
45 return thread_sp->GetSelectedFrame().get();
46 return nullptr;
47}
48
Enrico Granataf5196282012-09-04 18:48:21 +000049bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000050lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
51 const char* target_type,
52 const char* selector,
53 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000054{
55 if (!target_type || !*target_type)
56 return false;
57 if (!selector || !*selector)
58 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000059 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000060 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000061 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
62 lldb::ValueObjectSP result_sp;
63 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +000064 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf5196282012-09-04 18:48:21 +000065 if (!target || !stack_frame)
66 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000067
Jim Ingham35e1bda2012-10-16 21:41:58 +000068 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000069 options.SetCoerceToId(false);
70 options.SetUnwindOnError(true);
71 options.SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000072
Enrico Granataf5196282012-09-04 18:48:21 +000073 target->EvaluateExpression(expr.GetData(),
74 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000075 result_sp,
76 options);
Enrico Granataf5196282012-09-04 18:48:21 +000077 if (!result_sp)
78 return false;
79 value = result_sp->GetValueAsUnsigned(0);
80 return true;
81}
82
Enrico Granataf615b802013-02-15 23:38:37 +000083bool
84lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
85 const char* target_type,
86 const char* selector,
87 Stream &stream)
88{
89 if (!target_type || !*target_type)
90 return false;
91 if (!selector || !*selector)
92 return false;
93 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +000094 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +000095 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
96 lldb::ValueObjectSP result_sp;
97 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +000098 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granataf615b802013-02-15 23:38:37 +000099 if (!target || !stack_frame)
100 return false;
101
102 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000103 options.SetCoerceToId(false);
104 options.SetUnwindOnError(true);
105 options.SetKeepInMemory(true);
106 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataf615b802013-02-15 23:38:37 +0000107
108 target->EvaluateExpression(expr.GetData(),
109 stack_frame,
110 result_sp,
111 options);
112 if (!result_sp)
113 return false;
114 stream.Printf("%s",result_sp->GetSummaryAsCString());
115 return true;
116}
117
Enrico Granatab2698cd2012-09-13 18:27:09 +0000118lldb::ValueObjectSP
119lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
120 const char* return_type,
121 const char* selector,
122 uint64_t index)
123{
124 lldb::ValueObjectSP valobj_sp;
125 if (!return_type || !*return_type)
126 return valobj_sp;
127 if (!selector || !*selector)
128 return valobj_sp;
129 StreamString expr_path_stream;
130 valobj.GetExpressionPath(expr_path_stream, false);
131 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000132 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000133 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
134 lldb::ValueObjectSP result_sp;
135 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000136 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000137 if (!target || !stack_frame)
138 return valobj_sp;
139
Jim Ingham35e1bda2012-10-16 21:41:58 +0000140 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000141 options.SetCoerceToId(false);
142 options.SetUnwindOnError(true);
143 options.SetKeepInMemory(true);
144 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000145
146 target->EvaluateExpression(expr.GetData(),
147 stack_frame,
148 valobj_sp,
149 options);
150 return valobj_sp;
151}
152
153lldb::ValueObjectSP
154lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
155 const char* return_type,
156 const char* selector,
157 const char* key)
158{
159 lldb::ValueObjectSP valobj_sp;
160 if (!return_type || !*return_type)
161 return valobj_sp;
162 if (!selector || !*selector)
163 return valobj_sp;
164 if (!key || !*key)
165 return valobj_sp;
166 StreamString expr_path_stream;
167 valobj.GetExpressionPath(expr_path_stream, false);
168 StreamString expr;
169 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
170 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
171 lldb::ValueObjectSP result_sp;
172 Target* target = exe_ctx.GetTargetPtr();
Enrico Granataba8eb122014-07-30 21:07:50 +0000173 StackFrame* stack_frame = GetViableFrame(exe_ctx);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000174 if (!target || !stack_frame)
175 return valobj_sp;
176
Jim Ingham35e1bda2012-10-16 21:41:58 +0000177 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000178 options.SetCoerceToId(false);
179 options.SetUnwindOnError(true);
180 options.SetKeepInMemory(true);
181 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000182
183 target->EvaluateExpression(expr.GetData(),
184 stack_frame,
185 valobj_sp,
186 options);
187 return valobj_sp;
188}
189
Enrico Granata93d59662013-01-14 23:53:26 +0000190// use this call if you already have an LLDB-side buffer for the data
191template<typename SourceDataType>
Enrico Granataf68df122013-01-10 22:08:35 +0000192static bool
Enrico Granata93d59662013-01-14 23:53:26 +0000193DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
194 const SourceDataType*,
195 UTF8**,
196 UTF8*,
197 ConversionFlags),
198 DataExtractor& data,
199 Stream& stream,
200 char prefix_token = '@',
201 char quote = '"',
Enrico Granatad83bfce2013-04-02 21:25:34 +0000202 uint32_t sourceSize = 0)
Enrico Granataf68df122013-01-10 22:08:35 +0000203{
Enrico Granata93d59662013-01-14 23:53:26 +0000204 if (prefix_token != 0)
205 stream.Printf("%c",prefix_token);
206 if (quote != 0)
207 stream.Printf("%c",quote);
208 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf68df122013-01-10 22:08:35 +0000209 {
Enrico Granata93d59662013-01-14 23:53:26 +0000210 const int bufferSPSize = data.GetByteSize();
211 if (sourceSize == 0)
212 {
213 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Claytonaa4c47a2013-02-08 21:59:34 +0000214 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granata93d59662013-01-14 23:53:26 +0000215 }
216
217 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000218 SourceDataType *data_end_ptr = data_ptr + sourceSize;
219
220 while (data_ptr < data_end_ptr)
221 {
222 if (!*data_ptr)
223 {
224 data_end_ptr = data_ptr;
225 break;
226 }
227 data_ptr++;
228 }
229
Enrico Granata93d59662013-01-14 23:53:26 +0000230 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000231
Enrico Granata38352042013-01-11 02:44:00 +0000232 lldb::DataBufferSP utf8_data_buffer_sp;
233 UTF8* utf8_data_ptr = nullptr;
234 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granata93d59662013-01-14 23:53:26 +0000235
Enrico Granataf68df122013-01-10 22:08:35 +0000236 if (ConvertFunction)
Enrico Granata38352042013-01-11 02:44:00 +0000237 {
Enrico Granata56768392013-04-23 20:05:05 +0000238 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
Enrico Granata38352042013-01-11 02:44:00 +0000239 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
Enrico Granata56768392013-04-23 20:05:05 +0000240 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
Enrico Granataf68df122013-01-10 22:08:35 +0000241 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata38352042013-01-11 02:44:00 +0000242 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
243 }
Enrico Granataf68df122013-01-10 22:08:35 +0000244 else
245 {
246 // just copy the pointers - the cast is necessary to make the compiler happy
247 // but this should only happen if we are reading UTF8 data
248 utf8_data_ptr = (UTF8*)data_ptr;
249 utf8_data_end_ptr = (UTF8*)data_end_ptr;
250 }
251
Enrico Granata3309d882013-01-12 01:00:22 +0000252 // since we tend to accept partial data (and even partially malformed data)
253 // we might end up with no NULL terminator before the end_ptr
254 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf68df122013-01-10 22:08:35 +0000255 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
256 {
257 if (!*utf8_data_ptr)
258 break;
259 stream.Printf("%c",*utf8_data_ptr);
260 }
Enrico Granata93d59662013-01-14 23:53:26 +0000261 }
262 if (quote != 0)
263 stream.Printf("%c",quote);
264 return true;
265}
266
267template<typename SourceDataType>
Enrico Granata56768392013-04-23 20:05:05 +0000268class ReadUTFBufferAndDumpToStreamOptions
Enrico Granata93d59662013-01-14 23:53:26 +0000269{
Enrico Granata56768392013-04-23 20:05:05 +0000270public:
271 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
272 const SourceDataType*,
273 UTF8**,
274 UTF8*,
275 ConversionFlags);
276
277 ReadUTFBufferAndDumpToStreamOptions () :
278 m_conversion_function(NULL),
279 m_location(0),
280 m_process_sp(),
281 m_stream(NULL),
282 m_prefix_token('@'),
283 m_quote('"'),
284 m_source_size(0),
285 m_needs_zero_termination(true)
286 {
287 }
288
289 ReadUTFBufferAndDumpToStreamOptions&
290 SetConversionFunction (ConvertFunctionType f)
291 {
292 m_conversion_function = f;
293 return *this;
294 }
295
296 ConvertFunctionType
297 GetConversionFunction () const
298 {
299 return m_conversion_function;
300 }
301
302 ReadUTFBufferAndDumpToStreamOptions&
303 SetLocation (uint64_t l)
304 {
305 m_location = l;
306 return *this;
307 }
308
309 uint64_t
310 GetLocation () const
311 {
312 return m_location;
313 }
314
315 ReadUTFBufferAndDumpToStreamOptions&
316 SetProcessSP (ProcessSP p)
317 {
318 m_process_sp = p;
319 return *this;
320 }
321
322 ProcessSP
323 GetProcessSP () const
324 {
325 return m_process_sp;
326 }
327
328 ReadUTFBufferAndDumpToStreamOptions&
329 SetStream (Stream* s)
330 {
331 m_stream = s;
332 return *this;
333 }
334
335 Stream*
336 GetStream () const
337 {
338 return m_stream;
339 }
340
341 ReadUTFBufferAndDumpToStreamOptions&
342 SetPrefixToken (char p)
343 {
344 m_prefix_token = p;
345 return *this;
346 }
347
348 char
349 GetPrefixToken () const
350 {
351 return m_prefix_token;
352 }
353
354 ReadUTFBufferAndDumpToStreamOptions&
355 SetQuote (char q)
356 {
357 m_quote = q;
358 return *this;
359 }
360
361 char
362 GetQuote () const
363 {
364 return m_quote;
365 }
366
367 ReadUTFBufferAndDumpToStreamOptions&
368 SetSourceSize (uint32_t s)
369 {
370 m_source_size = s;
371 return *this;
372 }
373
374 uint32_t
375 GetSourceSize () const
376 {
377 return m_source_size;
378 }
379
380 ReadUTFBufferAndDumpToStreamOptions&
381 SetNeedsZeroTermination (bool z)
382 {
383 m_needs_zero_termination = z;
384 return *this;
385 }
386
387 bool
388 GetNeedsZeroTermination () const
389 {
390 return m_needs_zero_termination;
391 }
392
393private:
394 ConvertFunctionType m_conversion_function;
395 uint64_t m_location;
396 ProcessSP m_process_sp;
397 Stream* m_stream;
398 char m_prefix_token;
399 char m_quote;
400 uint32_t m_source_size;
401 bool m_needs_zero_termination;
402};
403
404template<typename SourceDataType>
405static bool
406ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
407{
408 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
Enrico Granata93d59662013-01-14 23:53:26 +0000409 return false;
Enrico Granata56768392013-04-23 20:05:05 +0000410
411 ProcessSP process_sp(options.GetProcessSP());
412
Enrico Granata93d59662013-01-14 23:53:26 +0000413 if (!process_sp)
414 return false;
415
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000416 const int type_width = sizeof(SourceDataType);
417 const int origin_encoding = 8 * type_width ;
Enrico Granata93d59662013-01-14 23:53:26 +0000418 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
419 return false;
420 // if not UTF8, I need a conversion function to return proper UTF8
Enrico Granata56768392013-04-23 20:05:05 +0000421 if (origin_encoding != 8 && !options.GetConversionFunction())
422 return false;
423
424 if (!options.GetStream())
Enrico Granata93d59662013-01-14 23:53:26 +0000425 return false;
426
Enrico Granata56768392013-04-23 20:05:05 +0000427 uint32_t sourceSize = options.GetSourceSize();
428 bool needs_zero_terminator = options.GetNeedsZeroTermination();
429
Enrico Granata23ab35a2013-04-02 23:07:55 +0000430 if (!sourceSize)
Enrico Granata56768392013-04-23 20:05:05 +0000431 {
Enrico Granata23ab35a2013-04-02 23:07:55 +0000432 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
Enrico Granata56768392013-04-23 20:05:05 +0000433 needs_zero_terminator = true;
434 }
Enrico Granata23ab35a2013-04-02 23:07:55 +0000435 else
436 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
437
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000438 const int bufferSPSize = sourceSize * type_width;
Enrico Granata93d59662013-01-14 23:53:26 +0000439
Enrico Granata93d59662013-01-14 23:53:26 +0000440 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
441
442 if (!buffer_sp->GetBytes())
443 return false;
444
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000445 Error error;
446 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
447
Enrico Granata56768392013-04-23 20:05:05 +0000448 size_t data_read = 0;
449 if (needs_zero_terminator)
450 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
451 else
452 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
453
Enrico Granata93d59662013-01-14 23:53:26 +0000454 if (error.Fail() || data_read == 0)
455 {
Enrico Granata56768392013-04-23 20:05:05 +0000456 options.GetStream()->Printf("unable to read data");
Enrico Granataf68df122013-01-10 22:08:35 +0000457 return true;
458 }
Enrico Granata93d59662013-01-14 23:53:26 +0000459
460 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
461
Enrico Granata56768392013-04-23 20:05:05 +0000462 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
Enrico Granataf68df122013-01-10 22:08:35 +0000463}
464
465bool
466lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
467{
468 ProcessSP process_sp = valobj.GetProcessSP();
469 if (!process_sp)
470 return false;
471
472 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
473
474 if (!valobj_addr)
475 return false;
476
Enrico Granata56768392013-04-23 20:05:05 +0000477 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
478 options.SetLocation(valobj_addr);
479 options.SetConversionFunction(ConvertUTF16toUTF8);
480 options.SetProcessSP(process_sp);
481 options.SetStream(&stream);
482 options.SetPrefixToken('u');
483
484 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000485 {
486 stream.Printf("Summary Unavailable");
487 return true;
488 }
489
490 return true;
491}
492
493bool
494lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
495{
496 ProcessSP process_sp = valobj.GetProcessSP();
497 if (!process_sp)
498 return false;
499
500 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
501
502 if (!valobj_addr)
503 return false;
504
Enrico Granata56768392013-04-23 20:05:05 +0000505 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
506 options.SetLocation(valobj_addr);
507 options.SetConversionFunction(ConvertUTF32toUTF8);
508 options.SetProcessSP(process_sp);
509 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000510 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000511
512 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000513 {
514 stream.Printf("Summary Unavailable");
515 return true;
516 }
517
518 return true;
519}
520
521bool
522lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
523{
Enrico Granata38352042013-01-11 02:44:00 +0000524 ProcessSP process_sp = valobj.GetProcessSP();
525 if (!process_sp)
526 return false;
527
Enrico Granata3309d882013-01-12 01:00:22 +0000528 lldb::addr_t data_addr = 0;
529
530 if (valobj.IsPointerType())
531 data_addr = valobj.GetValueAsUnsigned(0);
532 else if (valobj.IsArrayType())
533 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000534
Enrico Granata3309d882013-01-12 01:00:22 +0000535 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000536 return false;
537
Greg Clayton57ee3062013-07-11 22:46:58 +0000538 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
539
Enrico Granata38352042013-01-11 02:44:00 +0000540 if (!ast)
541 return false;
542
Greg Clayton57ee3062013-07-11 22:46:58 +0000543 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
544 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata38352042013-01-11 02:44:00 +0000545
546 switch (wchar_size)
547 {
548 case 8:
Enrico Granata56768392013-04-23 20:05:05 +0000549 {
Enrico Granata38352042013-01-11 02:44:00 +0000550 // utf 8
Enrico Granata56768392013-04-23 20:05:05 +0000551
552 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
553 options.SetLocation(data_addr);
554 options.SetConversionFunction(nullptr);
555 options.SetProcessSP(process_sp);
556 options.SetStream(&stream);
557 options.SetPrefixToken('L');
558
559 return ReadUTFBufferAndDumpToStream(options);
560 }
Enrico Granata38352042013-01-11 02:44:00 +0000561 case 16:
Enrico Granata56768392013-04-23 20:05:05 +0000562 {
Enrico Granata38352042013-01-11 02:44:00 +0000563 // utf 16
Enrico Granata56768392013-04-23 20:05:05 +0000564 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
565 options.SetLocation(data_addr);
566 options.SetConversionFunction(ConvertUTF16toUTF8);
567 options.SetProcessSP(process_sp);
568 options.SetStream(&stream);
569 options.SetPrefixToken('L');
570
571 return ReadUTFBufferAndDumpToStream(options);
572 }
Enrico Granata38352042013-01-11 02:44:00 +0000573 case 32:
Enrico Granata56768392013-04-23 20:05:05 +0000574 {
Enrico Granata38352042013-01-11 02:44:00 +0000575 // utf 32
Enrico Granata56768392013-04-23 20:05:05 +0000576 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
577 options.SetLocation(data_addr);
578 options.SetConversionFunction(ConvertUTF32toUTF8);
579 options.SetProcessSP(process_sp);
580 options.SetStream(&stream);
581 options.SetPrefixToken('L');
582
583 return ReadUTFBufferAndDumpToStream(options);
584 }
Enrico Granata93d59662013-01-14 23:53:26 +0000585 default:
586 stream.Printf("size for wchar_t is not valid");
587 return true;
588 }
589 return true;
590}
591
592bool
593lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
594{
595 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000596 Error error;
597 valobj.GetData(data, error);
598
599 if (error.Fail())
600 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000601
602 std::string value;
603 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
604 if (!value.empty())
605 stream.Printf("%s ", value.c_str());
606
607 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
608}
609
610bool
611lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
612{
613 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000614 Error error;
615 valobj.GetData(data, error);
616
617 if (error.Fail())
618 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000619
620 std::string value;
621 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
622 if (!value.empty())
623 stream.Printf("%s ", value.c_str());
624
625 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
626}
627
628bool
629lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
630{
631 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000632 Error error;
633 valobj.GetData(data, error);
634
635 if (error.Fail())
636 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000637
Greg Clayton57ee3062013-07-11 22:46:58 +0000638 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
Enrico Granata93d59662013-01-14 23:53:26 +0000639
640 if (!ast)
641 return false;
642
Greg Clayton57ee3062013-07-11 22:46:58 +0000643 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
644 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata93d59662013-01-14 23:53:26 +0000645 std::string value;
646
Enrico Granata93d59662013-01-14 23:53:26 +0000647 switch (wchar_size)
648 {
649 case 8:
650 // utf 8
651 valobj.GetValueAsCString(lldb::eFormatChar, value);
652 if (!value.empty())
653 stream.Printf("%s ", value.c_str());
654 return DumpUTFBufferToStream<UTF8>(nullptr,
655 data,
656 stream,
657 'L',
658 '\'',
659 1);
660 case 16:
661 // utf 16
662 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
663 if (!value.empty())
664 stream.Printf("%s ", value.c_str());
665 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
666 data,
667 stream,
668 'L',
669 '\'',
670 1);
671 case 32:
672 // utf 32
673 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
674 if (!value.empty())
675 stream.Printf("%s ", value.c_str());
676 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
677 data,
678 stream,
679 'L',
680 '\'',
681 1);
Enrico Granata38352042013-01-11 02:44:00 +0000682 default:
683 stream.Printf("size for wchar_t is not valid");
684 return true;
685 }
686 return true;
Enrico Granataf68df122013-01-10 22:08:35 +0000687}
688
Enrico Granataa3962a72013-05-15 00:47:46 +0000689// the field layout in a libc++ string (cap, side, data or data, size, cap)
690enum LibcxxStringLayoutMode
691{
692 eLibcxxStringLayoutModeCSD = 0,
693 eLibcxxStringLayoutModeDSC = 1,
694 eLibcxxStringLayoutModeInvalid = 0xffff
695};
696
697// this function abstracts away the layout and mode details of a libc++ string
698// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000699static bool
700ExtractLibcxxStringInfo (ValueObject& valobj,
701 ValueObjectSP &location_sp,
702 uint64_t& size)
703{
704 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
705 if (!D)
706 return false;
707
Enrico Granataa3962a72013-05-15 00:47:46 +0000708 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
709
710 // this child should exist
711 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000712 return false;
713
Enrico Granataa3962a72013-05-15 00:47:46 +0000714 ConstString g_data_name("__data_");
715 ConstString g_size_name("__size_");
716 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
717 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
718 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000719
Enrico Granataa3962a72013-05-15 00:47:46 +0000720 if (layout == eLibcxxStringLayoutModeDSC)
721 {
722 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
723 if (!size_mode)
724 return false;
725
726 if (size_mode->GetName() != g_size_name)
727 {
728 // we are hitting the padding structure, move along
729 size_mode = D->GetChildAtIndexPath({1,1,1});
730 if (!size_mode)
731 return false;
732 }
733
734 size_mode_value = (size_mode->GetValueAsUnsigned(0));
735 short_mode = ((size_mode_value & 0x80) == 0);
736 }
737 else
738 {
739 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
740 if (!size_mode)
741 return false;
742
743 size_mode_value = (size_mode->GetValueAsUnsigned(0));
744 short_mode = ((size_mode_value & 1) == 0);
745 }
746
747 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000748 {
749 ValueObjectSP s(D->GetChildAtIndex(1, true));
750 if (!s)
751 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000752 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
753 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000754 return (location_sp.get() != nullptr);
755 }
756 else
757 {
758 ValueObjectSP l(D->GetChildAtIndex(0, true));
759 if (!l)
760 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000761 // we can use the layout_decider object as the data pointer
762 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000763 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
764 if (!size_vo || !location_sp)
765 return false;
766 size = size_vo->GetValueAsUnsigned(0);
767 return true;
768 }
769}
770
771bool
772lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
773{
774 uint64_t size = 0;
775 ValueObjectSP location_sp((ValueObject*)nullptr);
776 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
777 return false;
778 if (size == 0)
779 {
780 stream.Printf("L\"\"");
781 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000782 }
Enrico Granata3309d882013-01-12 01:00:22 +0000783 if (!location_sp)
784 return false;
785 return WCharStringSummaryProvider(*location_sp.get(), stream);
786}
787
788bool
789lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
790{
791 uint64_t size = 0;
792 ValueObjectSP location_sp((ValueObject*)nullptr);
793 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
794 return false;
795 if (size == 0)
796 {
797 stream.Printf("\"\"");
798 return true;
799 }
800 if (!location_sp)
801 return false;
802 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000803 if (location_sp->ReadPointedString(stream,
804 error,
805 0, // max length is decided by the settings
806 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
807 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000808 return error.Success();
809}
810
Enrico Granata55900862013-03-15 18:55:30 +0000811bool
812lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
813{
814 ProcessSP process_sp = valobj.GetProcessSP();
815 if (!process_sp)
816 return false;
817
818 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
819
820 if (!runtime)
821 return false;
822
Greg Clayton03da4cc2013-04-19 21:31:16 +0000823 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000824
825 if (!descriptor.get() || !descriptor->IsValid())
826 return false;
827
828 const char* class_name = descriptor->GetClassName().GetCString();
829
830 if (!class_name || !*class_name)
831 return false;
832
833 stream.Printf("%s",class_name);
834 return true;
835}
836
Enrico Granatac76b97b2013-04-26 00:59:02 +0000837class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
838{
839public:
840 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
841 SyntheticChildrenFrontEnd(*valobj_sp.get())
842 {
843 }
844
845 virtual size_t
846 CalculateNumChildren ()
847 {
848 return 0;
849 }
850
851 virtual lldb::ValueObjectSP
852 GetChildAtIndex (size_t idx)
853 {
854 return lldb::ValueObjectSP();
855 }
856
857 virtual bool
858 Update()
859 {
860 return false;
861 }
862
863 virtual bool
864 MightHaveChildren ()
865 {
866 return false;
867 }
868
869 virtual size_t
870 GetIndexOfChildWithName (const ConstString &name)
871 {
872 return UINT32_MAX;
873 }
874
875 virtual
876 ~ObjCClassSyntheticChildrenFrontEnd ()
877 {
878 }
879};
880
881SyntheticChildrenFrontEnd*
882lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
883{
884 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
885}
886
Enrico Granataf5196282012-09-04 18:48:21 +0000887template<bool needs_at>
888bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000889lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000890{
891 ProcessSP process_sp = valobj.GetProcessSP();
892 if (!process_sp)
893 return false;
894
895 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
896
897 if (!runtime)
898 return false;
899
900 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
901
902 if (!descriptor.get() || !descriptor->IsValid())
903 return false;
904
905 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
906 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
907
908 if (!valobj_addr)
909 return false;
910
911 uint64_t value = 0;
912
913 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000914
915 if (!class_name || !*class_name)
916 return false;
917
Enrico Granataf5196282012-09-04 18:48:21 +0000918 if (!strcmp(class_name,"NSConcreteData") ||
919 !strcmp(class_name,"NSConcreteMutableData") ||
920 !strcmp(class_name,"__NSCFData"))
921 {
922 uint32_t offset = (is_64bit ? 16 : 8);
923 Error error;
924 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
925 if (error.Fail())
926 return false;
927 }
928 else
929 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000930 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000931 return false;
932 }
933
Daniel Malead01b2952012-11-29 21:49:15 +0000934 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000935 (needs_at ? "@\"" : ""),
936 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000937 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000938 (needs_at ? "\"" : ""));
939
940 return true;
941}
942
Enrico Granata87f00b42013-02-21 20:31:18 +0000943static bool
944ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
945 lldb::ProcessSP& process_sp,
946 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000947 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000948 Error* error = NULL,
949 size_t *data_read = NULL,
950 char prefix_token = '@',
951 char quote = '"')
952{
953 Error my_error;
954 size_t my_data_read;
955 if (!process_sp || location == 0)
956 return false;
957
Enrico Granata23ab35a2013-04-02 23:07:55 +0000958 if (!size)
959 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
960 else
961 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000962
963 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
964
965 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
966
967 if (error)
968 *error = my_error;
969 if (data_read)
970 *data_read = my_data_read;
971
972 if (my_error.Fail())
973 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000974
975 dest.Printf("%c%c",prefix_token,quote);
976
Enrico Granata87f00b42013-02-21 20:31:18 +0000977 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000978 dest.Printf("%s",(char*)buffer_sp->GetBytes());
979
980 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000981
982 return true;
983}
984
Enrico Granataf5196282012-09-04 18:48:21 +0000985bool
Jason Molenda705b1802014-06-13 02:37:02 +0000986lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream)
987{
988 if (!descriptor)
989 return false;
990 uint64_t len_bits = 0, data_bits = 0;
991 if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
992 return false;
993
994 static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
995 static const int g_SixbitMaxLen = 9;
996 static const int g_fiveBitMaxLen = 11;
997
998 static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
999
1000 if (len_bits > g_fiveBitMaxLen)
1001 return false;
1002
1003 // this is a fairly ugly trick - pretend that the numeric value is actually a char*
1004 // this works under a few assumptions:
1005 // little endian architecture
1006 // sizeof(uint64_t) > g_MaxNonBitmaskedLen
1007 if (len_bits <= g_MaxNonBitmaskedLen)
1008 {
1009 stream.Printf("@\"%s\"",(const char*)&data_bits);
1010 return true;
1011 }
1012
1013 // if the data is bitmasked, we need to actually process the bytes
1014 uint8_t bitmask = 0;
1015 uint8_t shift_offset = 0;
1016
1017 if (len_bits <= g_SixbitMaxLen)
1018 {
1019 bitmask = 0x03f;
1020 shift_offset = 6;
1021 }
1022 else
1023 {
1024 bitmask = 0x01f;
1025 shift_offset = 5;
1026 }
1027
1028 std::vector<uint8_t> bytes;
1029 bytes.resize(len_bits);
1030 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
1031 {
1032 uint8_t packed = data_bits & bitmask;
1033 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
1034 }
1035
1036 stream.Printf("@\"%s\"",&bytes[0]);
1037 return true;
1038}
1039
1040bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001041lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +00001042{
1043 ProcessSP process_sp = valobj.GetProcessSP();
1044 if (!process_sp)
1045 return false;
1046
1047 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1048
1049 if (!runtime)
1050 return false;
1051
1052 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
1053
1054 if (!descriptor.get() || !descriptor->IsValid())
1055 return false;
1056
1057 uint32_t ptr_size = process_sp->GetAddressByteSize();
1058
1059 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1060
1061 if (!valobj_addr)
1062 return false;
1063
1064 const char* class_name = descriptor->GetClassName().GetCString();
1065
Enrico Granata60b81df2012-09-29 00:45:53 +00001066 if (!class_name || !*class_name)
1067 return false;
1068
Jason Molenda705b1802014-06-13 02:37:02 +00001069 bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
1070 // for a tagged pointer, the descriptor has everything we need
1071 if (is_tagged_ptr)
1072 return NSTaggedString_SummaryProvider(descriptor, stream);
1073
1074 // if not a tagged pointer that we know about, try the normal route
Enrico Granataf5196282012-09-04 18:48:21 +00001075 uint64_t info_bits_location = valobj_addr + ptr_size;
1076 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
1077 info_bits_location += 3;
1078
Enrico Granata87f00b42013-02-21 20:31:18 +00001079 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +00001080
1081 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
1082 if (error.Fail())
1083 return false;
1084
1085 bool is_mutable = (info_bits & 1) == 1;
1086 bool is_inline = (info_bits & 0x60) == 0;
1087 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
1088 bool is_unicode = (info_bits & 0x10) == 0x10;
1089 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001090 bool has_null = (info_bits & 8) == 8;
1091
1092 size_t explicit_length = 0;
1093 if (!has_null && has_explicit_length && !is_special)
1094 {
1095 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001096 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001097 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1098 else if (is_inline)
1099 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001100 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001101 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1102 else
1103 explicit_length_offset = 0;
1104
1105 if (explicit_length_offset)
1106 {
1107 explicit_length_offset = valobj_addr + explicit_length_offset;
1108 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1109 }
1110 }
1111
Enrico Granataf5196282012-09-04 18:48:21 +00001112 if (strcmp(class_name,"NSString") &&
1113 strcmp(class_name,"CFStringRef") &&
1114 strcmp(class_name,"CFMutableStringRef") &&
1115 strcmp(class_name,"__NSCFConstantString") &&
1116 strcmp(class_name,"__NSCFString") &&
1117 strcmp(class_name,"NSCFConstantString") &&
1118 strcmp(class_name,"NSCFString") &&
1119 strcmp(class_name,"NSPathStore2"))
1120 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001121 // not one of us - but tell me class name
1122 stream.Printf("class name = %s",class_name);
1123 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001124 }
1125
1126 if (is_mutable)
1127 {
1128 uint64_t location = 2 * ptr_size + valobj_addr;
1129 location = process_sp->ReadPointerFromMemory(location, error);
1130 if (error.Fail())
1131 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001132 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001133 {
1134 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1135 options.SetConversionFunction(ConvertUTF16toUTF8);
1136 options.SetLocation(location);
1137 options.SetProcessSP(process_sp);
1138 options.SetStream(&stream);
1139 options.SetPrefixToken('@');
1140 options.SetQuote('"');
1141 options.SetSourceSize(explicit_length);
1142 options.SetNeedsZeroTermination(false);
1143 return ReadUTFBufferAndDumpToStream (options);
1144 }
Enrico Granataf5196282012-09-04 18:48:21 +00001145 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001146 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001147 }
1148 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1149 {
1150 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001151 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001152 }
1153 else if (is_unicode)
1154 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001155 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001156 if (is_inline)
1157 {
1158 if (!has_explicit_length)
1159 {
1160 stream.Printf("found new combo");
1161 return true;
1162 }
1163 else
1164 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001165 }
Enrico Granataf5196282012-09-04 18:48:21 +00001166 else
1167 {
1168 location = process_sp->ReadPointerFromMemory(location, error);
1169 if (error.Fail())
1170 return false;
1171 }
Enrico Granata56768392013-04-23 20:05:05 +00001172 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1173 options.SetConversionFunction(ConvertUTF16toUTF8);
1174 options.SetLocation(location);
1175 options.SetProcessSP(process_sp);
1176 options.SetStream(&stream);
1177 options.SetPrefixToken('@');
1178 options.SetQuote('"');
1179 options.SetSourceSize(explicit_length);
1180 options.SetNeedsZeroTermination(has_explicit_length == false);
1181 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001182 }
1183 else if (is_special)
1184 {
1185 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001186 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1187 options.SetConversionFunction(ConvertUTF16toUTF8);
1188 options.SetLocation(location);
1189 options.SetProcessSP(process_sp);
1190 options.SetStream(&stream);
1191 options.SetPrefixToken('@');
1192 options.SetQuote('"');
1193 options.SetSourceSize(explicit_length);
1194 options.SetNeedsZeroTermination(has_explicit_length == false);
1195 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001196 }
1197 else if (is_inline)
1198 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001199 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001200 if (!has_explicit_length)
1201 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001202 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001203 }
1204 else
1205 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001206 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001207 location = process_sp->ReadPointerFromMemory(location, error);
1208 if (error.Fail())
1209 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +00001210 if (has_explicit_length && !has_null)
1211 explicit_length++; // account for the fact that there is no NULL and we need to have one added
Enrico Granatad83bfce2013-04-02 21:25:34 +00001212 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001213 }
Enrico Granataf5196282012-09-04 18:48:21 +00001214}
1215
Enrico Granataf175ad12012-10-03 23:53:45 +00001216bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001217lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1218{
1219 TargetSP target_sp(valobj.GetTargetSP());
1220 if (!target_sp)
1221 return false;
1222 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001223 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1224 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001225 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001226 pointer_value += addr_size;
1227 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001228 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001229 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001230 if (!child_ptr_sp)
1231 return false;
1232 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001233 Error error;
1234 child_ptr_sp->GetData(data, error);
1235 if (error.Fail())
1236 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001237 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1238 child_sp->GetValueAsUnsigned(0);
1239 if (child_sp)
1240 return NSStringSummaryProvider(*child_sp, stream);
1241 return false;
1242}
1243
1244bool
1245lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1246{
1247 return NSAttributedStringSummaryProvider(valobj, stream);
1248}
1249
1250bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001251lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1252{
1253 stream.Printf("%s",valobj.GetObjectDescription());
1254 return true;
1255}
1256
Enrico Granatab5887262012-10-29 21:18:03 +00001257bool
1258lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1259{
Greg Clayton57ee3062013-07-11 22:46:58 +00001260 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001261
1262 ValueObjectSP real_guy_sp = valobj.GetSP();
1263
Enrico Granata622be232014-10-21 20:52:14 +00001264 if (type_info & eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001265 {
1266 Error err;
1267 real_guy_sp = valobj.Dereference(err);
1268 if (err.Fail() || !real_guy_sp)
1269 return false;
1270 }
Enrico Granata622be232014-10-21 20:52:14 +00001271 else if (type_info & eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001272 {
1273 real_guy_sp = valobj.GetChildAtIndex(0, true);
1274 if (!real_guy_sp)
1275 return false;
1276 }
1277 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1278 if (value == 0)
1279 {
1280 stream.Printf("NO");
1281 return true;
1282 }
1283 stream.Printf("YES");
1284 return true;
1285}
1286
1287template <bool is_sel_ptr>
1288bool
1289lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1290{
Enrico Granata75dfb432013-02-15 00:06:04 +00001291 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001292
Greg Clayton57ee3062013-07-11 22:46:58 +00001293 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1294
1295 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001296 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001297
Enrico Granatab5887262012-10-29 21:18:03 +00001298 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1299
Enrico Granata75dfb432013-02-15 00:06:04 +00001300 if (is_sel_ptr)
1301 {
1302 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1303 if (data_address == LLDB_INVALID_ADDRESS)
1304 return false;
1305 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1306 }
1307 else
1308 {
1309 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001310 Error error;
1311 valobj.GetData(data, error);
1312 if (error.Fail())
1313 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001314 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1315 }
Enrico Granatab5887262012-10-29 21:18:03 +00001316
Enrico Granata75dfb432013-02-15 00:06:04 +00001317 if (!valobj_sp)
1318 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001319
1320 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1321 return true;
1322}
1323
Enrico Granata6d37cc62013-03-19 00:27:22 +00001324// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1325// this call gives the POSIX equivalent of the Cocoa epoch
1326time_t
Enrico Granata92373532013-03-19 22:58:48 +00001327lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001328{
1329 static time_t epoch = 0;
1330 if (!epoch)
1331 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001332#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001333 tzset();
1334 tm tm_epoch;
1335 tm_epoch.tm_sec = 0;
1336 tm_epoch.tm_hour = 0;
1337 tm_epoch.tm_min = 0;
1338 tm_epoch.tm_mon = 0;
1339 tm_epoch.tm_mday = 1;
1340 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1341 tm_epoch.tm_isdst = -1;
1342 tm_epoch.tm_gmtoff = 0;
1343 tm_epoch.tm_zone = NULL;
1344 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001345#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001346 }
1347 return epoch;
1348}
1349
Greg Claytonc7bece562013-01-25 18:06:21 +00001350size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001351lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001352{
1353 if (!item_name || !*item_name)
1354 return UINT32_MAX;
1355 if (*item_name != '[')
1356 return UINT32_MAX;
1357 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001358 char* endptr = NULL;
1359 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1360 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001361 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001362 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001363 return UINT32_MAX;
1364 return idx;
1365}
1366
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001367lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1368 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001369SyntheticChildrenFrontEnd(*valobj_sp.get()),
1370m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001371m_item_name(item_name),
1372m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001373{
1374 if (valobj_sp)
1375 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001376}
1377
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001378bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001379lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001380{
Enrico Granata6eca3552013-03-28 18:50:54 +00001381 m_item_sp.reset();
1382
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001383 ValueObjectSP valobj_sp = m_backend.GetSP();
1384 if (!valobj_sp)
1385 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001386
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001387 if (!valobj_sp)
1388 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001389
1390 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1391 if (!item_ptr)
1392 return false;
1393 if (item_ptr->GetValueAsUnsigned(0) == 0)
1394 return false;
1395 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001396 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Greg Clayton57ee3062013-07-11 22:46:58 +00001397 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType());
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001398 if (err.Fail())
1399 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001400 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001401}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001402
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001403size_t
1404lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1405{
1406 return 1;
1407}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001408
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001409lldb::ValueObjectSP
1410lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1411{
1412 if (idx == 0)
1413 return m_item_sp;
1414 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001415}
1416
1417bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001418lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001419{
1420 return true;
1421}
1422
1423size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001424lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001425{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001426 if (name == ConstString("item"))
1427 return 0;
1428 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001429}
1430
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001431lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001432{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001433}
1434
Enrico Granataf5196282012-09-04 18:48:21 +00001435template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001436lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1437
1438template bool
1439lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001440
1441template bool
1442lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1443
1444template bool
1445lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;