blob: 04f090dd15b615fe419fd499d356c6083f097f27 [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/ObjCLanguageRuntime.h"
24#include "lldb/Target/Target.h"
25
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
32bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000033lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
34 const char* target_type,
35 const char* selector,
36 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000037{
38 if (!target_type || !*target_type)
39 return false;
40 if (!selector || !*selector)
41 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000042 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000043 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000044 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
45 lldb::ValueObjectSP result_sp;
46 Target* target = exe_ctx.GetTargetPtr();
Jason Molendab57e4a12013-11-04 09:33:30 +000047 StackFrame* stack_frame = exe_ctx.GetFramePtr();
Enrico Granataf5196282012-09-04 18:48:21 +000048 if (!target || !stack_frame)
49 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000050
Jim Ingham35e1bda2012-10-16 21:41:58 +000051 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000052 options.SetCoerceToId(false);
53 options.SetUnwindOnError(true);
54 options.SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000055
Enrico Granataf5196282012-09-04 18:48:21 +000056 target->EvaluateExpression(expr.GetData(),
57 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000058 result_sp,
59 options);
Enrico Granataf5196282012-09-04 18:48:21 +000060 if (!result_sp)
61 return false;
62 value = result_sp->GetValueAsUnsigned(0);
63 return true;
64}
65
Enrico Granataf615b802013-02-15 23:38:37 +000066bool
67lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
68 const char* target_type,
69 const char* selector,
70 Stream &stream)
71{
72 if (!target_type || !*target_type)
73 return false;
74 if (!selector || !*selector)
75 return false;
76 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +000077 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +000078 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
79 lldb::ValueObjectSP result_sp;
80 Target* target = exe_ctx.GetTargetPtr();
Jason Molendab57e4a12013-11-04 09:33:30 +000081 StackFrame* stack_frame = exe_ctx.GetFramePtr();
Enrico Granataf615b802013-02-15 23:38:37 +000082 if (!target || !stack_frame)
83 return false;
84
85 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +000086 options.SetCoerceToId(false);
87 options.SetUnwindOnError(true);
88 options.SetKeepInMemory(true);
89 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataf615b802013-02-15 23:38:37 +000090
91 target->EvaluateExpression(expr.GetData(),
92 stack_frame,
93 result_sp,
94 options);
95 if (!result_sp)
96 return false;
97 stream.Printf("%s",result_sp->GetSummaryAsCString());
98 return true;
99}
100
Enrico Granatab2698cd2012-09-13 18:27:09 +0000101lldb::ValueObjectSP
102lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
103 const char* return_type,
104 const char* selector,
105 uint64_t index)
106{
107 lldb::ValueObjectSP valobj_sp;
108 if (!return_type || !*return_type)
109 return valobj_sp;
110 if (!selector || !*selector)
111 return valobj_sp;
112 StreamString expr_path_stream;
113 valobj.GetExpressionPath(expr_path_stream, false);
114 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000115 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000116 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
117 lldb::ValueObjectSP result_sp;
118 Target* target = exe_ctx.GetTargetPtr();
Jason Molendab57e4a12013-11-04 09:33:30 +0000119 StackFrame* stack_frame = exe_ctx.GetFramePtr();
Enrico Granatab2698cd2012-09-13 18:27:09 +0000120 if (!target || !stack_frame)
121 return valobj_sp;
122
Jim Ingham35e1bda2012-10-16 21:41:58 +0000123 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000124 options.SetCoerceToId(false);
125 options.SetUnwindOnError(true);
126 options.SetKeepInMemory(true);
127 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000128
129 target->EvaluateExpression(expr.GetData(),
130 stack_frame,
131 valobj_sp,
132 options);
133 return valobj_sp;
134}
135
136lldb::ValueObjectSP
137lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
138 const char* return_type,
139 const char* selector,
140 const char* key)
141{
142 lldb::ValueObjectSP valobj_sp;
143 if (!return_type || !*return_type)
144 return valobj_sp;
145 if (!selector || !*selector)
146 return valobj_sp;
147 if (!key || !*key)
148 return valobj_sp;
149 StreamString expr_path_stream;
150 valobj.GetExpressionPath(expr_path_stream, false);
151 StreamString expr;
152 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
153 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
154 lldb::ValueObjectSP result_sp;
155 Target* target = exe_ctx.GetTargetPtr();
Jason Molendab57e4a12013-11-04 09:33:30 +0000156 StackFrame* stack_frame = exe_ctx.GetFramePtr();
Enrico Granatab2698cd2012-09-13 18:27:09 +0000157 if (!target || !stack_frame)
158 return valobj_sp;
159
Jim Ingham35e1bda2012-10-16 21:41:58 +0000160 EvaluateExpressionOptions options;
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000161 options.SetCoerceToId(false);
162 options.SetUnwindOnError(true);
163 options.SetKeepInMemory(true);
164 options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000165
166 target->EvaluateExpression(expr.GetData(),
167 stack_frame,
168 valobj_sp,
169 options);
170 return valobj_sp;
171}
172
Enrico Granata93d59662013-01-14 23:53:26 +0000173// use this call if you already have an LLDB-side buffer for the data
174template<typename SourceDataType>
Enrico Granataf68df122013-01-10 22:08:35 +0000175static bool
Enrico Granata93d59662013-01-14 23:53:26 +0000176DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
177 const SourceDataType*,
178 UTF8**,
179 UTF8*,
180 ConversionFlags),
181 DataExtractor& data,
182 Stream& stream,
183 char prefix_token = '@',
184 char quote = '"',
Enrico Granatad83bfce2013-04-02 21:25:34 +0000185 uint32_t sourceSize = 0)
Enrico Granataf68df122013-01-10 22:08:35 +0000186{
Enrico Granata93d59662013-01-14 23:53:26 +0000187 if (prefix_token != 0)
188 stream.Printf("%c",prefix_token);
189 if (quote != 0)
190 stream.Printf("%c",quote);
191 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf68df122013-01-10 22:08:35 +0000192 {
Enrico Granata93d59662013-01-14 23:53:26 +0000193 const int bufferSPSize = data.GetByteSize();
194 if (sourceSize == 0)
195 {
196 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Claytonaa4c47a2013-02-08 21:59:34 +0000197 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granata93d59662013-01-14 23:53:26 +0000198 }
199
200 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000201 SourceDataType *data_end_ptr = data_ptr + sourceSize;
202
203 while (data_ptr < data_end_ptr)
204 {
205 if (!*data_ptr)
206 {
207 data_end_ptr = data_ptr;
208 break;
209 }
210 data_ptr++;
211 }
212
Enrico Granata93d59662013-01-14 23:53:26 +0000213 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000214
Enrico Granata38352042013-01-11 02:44:00 +0000215 lldb::DataBufferSP utf8_data_buffer_sp;
216 UTF8* utf8_data_ptr = nullptr;
217 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granata93d59662013-01-14 23:53:26 +0000218
Enrico Granataf68df122013-01-10 22:08:35 +0000219 if (ConvertFunction)
Enrico Granata38352042013-01-11 02:44:00 +0000220 {
Enrico Granata56768392013-04-23 20:05:05 +0000221 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
Enrico Granata38352042013-01-11 02:44:00 +0000222 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
Enrico Granata56768392013-04-23 20:05:05 +0000223 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
Enrico Granataf68df122013-01-10 22:08:35 +0000224 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata38352042013-01-11 02:44:00 +0000225 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
226 }
Enrico Granataf68df122013-01-10 22:08:35 +0000227 else
228 {
229 // just copy the pointers - the cast is necessary to make the compiler happy
230 // but this should only happen if we are reading UTF8 data
231 utf8_data_ptr = (UTF8*)data_ptr;
232 utf8_data_end_ptr = (UTF8*)data_end_ptr;
233 }
234
Enrico Granata3309d882013-01-12 01:00:22 +0000235 // since we tend to accept partial data (and even partially malformed data)
236 // we might end up with no NULL terminator before the end_ptr
237 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf68df122013-01-10 22:08:35 +0000238 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
239 {
240 if (!*utf8_data_ptr)
241 break;
242 stream.Printf("%c",*utf8_data_ptr);
243 }
Enrico Granata93d59662013-01-14 23:53:26 +0000244 }
245 if (quote != 0)
246 stream.Printf("%c",quote);
247 return true;
248}
249
250template<typename SourceDataType>
Enrico Granata56768392013-04-23 20:05:05 +0000251class ReadUTFBufferAndDumpToStreamOptions
Enrico Granata93d59662013-01-14 23:53:26 +0000252{
Enrico Granata56768392013-04-23 20:05:05 +0000253public:
254 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
255 const SourceDataType*,
256 UTF8**,
257 UTF8*,
258 ConversionFlags);
259
260 ReadUTFBufferAndDumpToStreamOptions () :
261 m_conversion_function(NULL),
262 m_location(0),
263 m_process_sp(),
264 m_stream(NULL),
265 m_prefix_token('@'),
266 m_quote('"'),
267 m_source_size(0),
268 m_needs_zero_termination(true)
269 {
270 }
271
272 ReadUTFBufferAndDumpToStreamOptions&
273 SetConversionFunction (ConvertFunctionType f)
274 {
275 m_conversion_function = f;
276 return *this;
277 }
278
279 ConvertFunctionType
280 GetConversionFunction () const
281 {
282 return m_conversion_function;
283 }
284
285 ReadUTFBufferAndDumpToStreamOptions&
286 SetLocation (uint64_t l)
287 {
288 m_location = l;
289 return *this;
290 }
291
292 uint64_t
293 GetLocation () const
294 {
295 return m_location;
296 }
297
298 ReadUTFBufferAndDumpToStreamOptions&
299 SetProcessSP (ProcessSP p)
300 {
301 m_process_sp = p;
302 return *this;
303 }
304
305 ProcessSP
306 GetProcessSP () const
307 {
308 return m_process_sp;
309 }
310
311 ReadUTFBufferAndDumpToStreamOptions&
312 SetStream (Stream* s)
313 {
314 m_stream = s;
315 return *this;
316 }
317
318 Stream*
319 GetStream () const
320 {
321 return m_stream;
322 }
323
324 ReadUTFBufferAndDumpToStreamOptions&
325 SetPrefixToken (char p)
326 {
327 m_prefix_token = p;
328 return *this;
329 }
330
331 char
332 GetPrefixToken () const
333 {
334 return m_prefix_token;
335 }
336
337 ReadUTFBufferAndDumpToStreamOptions&
338 SetQuote (char q)
339 {
340 m_quote = q;
341 return *this;
342 }
343
344 char
345 GetQuote () const
346 {
347 return m_quote;
348 }
349
350 ReadUTFBufferAndDumpToStreamOptions&
351 SetSourceSize (uint32_t s)
352 {
353 m_source_size = s;
354 return *this;
355 }
356
357 uint32_t
358 GetSourceSize () const
359 {
360 return m_source_size;
361 }
362
363 ReadUTFBufferAndDumpToStreamOptions&
364 SetNeedsZeroTermination (bool z)
365 {
366 m_needs_zero_termination = z;
367 return *this;
368 }
369
370 bool
371 GetNeedsZeroTermination () const
372 {
373 return m_needs_zero_termination;
374 }
375
376private:
377 ConvertFunctionType m_conversion_function;
378 uint64_t m_location;
379 ProcessSP m_process_sp;
380 Stream* m_stream;
381 char m_prefix_token;
382 char m_quote;
383 uint32_t m_source_size;
384 bool m_needs_zero_termination;
385};
386
387template<typename SourceDataType>
388static bool
389ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
390{
391 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
Enrico Granata93d59662013-01-14 23:53:26 +0000392 return false;
Enrico Granata56768392013-04-23 20:05:05 +0000393
394 ProcessSP process_sp(options.GetProcessSP());
395
Enrico Granata93d59662013-01-14 23:53:26 +0000396 if (!process_sp)
397 return false;
398
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000399 const int type_width = sizeof(SourceDataType);
400 const int origin_encoding = 8 * type_width ;
Enrico Granata93d59662013-01-14 23:53:26 +0000401 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
402 return false;
403 // if not UTF8, I need a conversion function to return proper UTF8
Enrico Granata56768392013-04-23 20:05:05 +0000404 if (origin_encoding != 8 && !options.GetConversionFunction())
405 return false;
406
407 if (!options.GetStream())
Enrico Granata93d59662013-01-14 23:53:26 +0000408 return false;
409
Enrico Granata56768392013-04-23 20:05:05 +0000410 uint32_t sourceSize = options.GetSourceSize();
411 bool needs_zero_terminator = options.GetNeedsZeroTermination();
412
Enrico Granata23ab35a2013-04-02 23:07:55 +0000413 if (!sourceSize)
Enrico Granata56768392013-04-23 20:05:05 +0000414 {
Enrico Granata23ab35a2013-04-02 23:07:55 +0000415 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
Enrico Granata56768392013-04-23 20:05:05 +0000416 needs_zero_terminator = true;
417 }
Enrico Granata23ab35a2013-04-02 23:07:55 +0000418 else
419 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
420
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000421 const int bufferSPSize = sourceSize * type_width;
Enrico Granata93d59662013-01-14 23:53:26 +0000422
Enrico Granata93d59662013-01-14 23:53:26 +0000423 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
424
425 if (!buffer_sp->GetBytes())
426 return false;
427
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000428 Error error;
429 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
430
Enrico Granata56768392013-04-23 20:05:05 +0000431 size_t data_read = 0;
432 if (needs_zero_terminator)
433 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
434 else
435 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
436
Enrico Granata93d59662013-01-14 23:53:26 +0000437 if (error.Fail() || data_read == 0)
438 {
Enrico Granata56768392013-04-23 20:05:05 +0000439 options.GetStream()->Printf("unable to read data");
Enrico Granataf68df122013-01-10 22:08:35 +0000440 return true;
441 }
Enrico Granata93d59662013-01-14 23:53:26 +0000442
443 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
444
Enrico Granata56768392013-04-23 20:05:05 +0000445 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
Enrico Granataf68df122013-01-10 22:08:35 +0000446}
447
448bool
449lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
450{
451 ProcessSP process_sp = valobj.GetProcessSP();
452 if (!process_sp)
453 return false;
454
455 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
456
457 if (!valobj_addr)
458 return false;
459
Enrico Granata56768392013-04-23 20:05:05 +0000460 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
461 options.SetLocation(valobj_addr);
462 options.SetConversionFunction(ConvertUTF16toUTF8);
463 options.SetProcessSP(process_sp);
464 options.SetStream(&stream);
465 options.SetPrefixToken('u');
466
467 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000468 {
469 stream.Printf("Summary Unavailable");
470 return true;
471 }
472
473 return true;
474}
475
476bool
477lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
478{
479 ProcessSP process_sp = valobj.GetProcessSP();
480 if (!process_sp)
481 return false;
482
483 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
484
485 if (!valobj_addr)
486 return false;
487
Enrico Granata56768392013-04-23 20:05:05 +0000488 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
489 options.SetLocation(valobj_addr);
490 options.SetConversionFunction(ConvertUTF32toUTF8);
491 options.SetProcessSP(process_sp);
492 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000493 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000494
495 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000496 {
497 stream.Printf("Summary Unavailable");
498 return true;
499 }
500
501 return true;
502}
503
504bool
505lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
506{
Enrico Granata38352042013-01-11 02:44:00 +0000507 ProcessSP process_sp = valobj.GetProcessSP();
508 if (!process_sp)
509 return false;
510
Enrico Granata3309d882013-01-12 01:00:22 +0000511 lldb::addr_t data_addr = 0;
512
513 if (valobj.IsPointerType())
514 data_addr = valobj.GetValueAsUnsigned(0);
515 else if (valobj.IsArrayType())
516 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000517
Enrico Granata3309d882013-01-12 01:00:22 +0000518 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000519 return false;
520
Greg Clayton57ee3062013-07-11 22:46:58 +0000521 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
522
Enrico Granata38352042013-01-11 02:44:00 +0000523 if (!ast)
524 return false;
525
Greg Clayton57ee3062013-07-11 22:46:58 +0000526 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
527 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata38352042013-01-11 02:44:00 +0000528
529 switch (wchar_size)
530 {
531 case 8:
Enrico Granata56768392013-04-23 20:05:05 +0000532 {
Enrico Granata38352042013-01-11 02:44:00 +0000533 // utf 8
Enrico Granata56768392013-04-23 20:05:05 +0000534
535 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
536 options.SetLocation(data_addr);
537 options.SetConversionFunction(nullptr);
538 options.SetProcessSP(process_sp);
539 options.SetStream(&stream);
540 options.SetPrefixToken('L');
541
542 return ReadUTFBufferAndDumpToStream(options);
543 }
Enrico Granata38352042013-01-11 02:44:00 +0000544 case 16:
Enrico Granata56768392013-04-23 20:05:05 +0000545 {
Enrico Granata38352042013-01-11 02:44:00 +0000546 // utf 16
Enrico Granata56768392013-04-23 20:05:05 +0000547 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
548 options.SetLocation(data_addr);
549 options.SetConversionFunction(ConvertUTF16toUTF8);
550 options.SetProcessSP(process_sp);
551 options.SetStream(&stream);
552 options.SetPrefixToken('L');
553
554 return ReadUTFBufferAndDumpToStream(options);
555 }
Enrico Granata38352042013-01-11 02:44:00 +0000556 case 32:
Enrico Granata56768392013-04-23 20:05:05 +0000557 {
Enrico Granata38352042013-01-11 02:44:00 +0000558 // utf 32
Enrico Granata56768392013-04-23 20:05:05 +0000559 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
560 options.SetLocation(data_addr);
561 options.SetConversionFunction(ConvertUTF32toUTF8);
562 options.SetProcessSP(process_sp);
563 options.SetStream(&stream);
564 options.SetPrefixToken('L');
565
566 return ReadUTFBufferAndDumpToStream(options);
567 }
Enrico Granata93d59662013-01-14 23:53:26 +0000568 default:
569 stream.Printf("size for wchar_t is not valid");
570 return true;
571 }
572 return true;
573}
574
575bool
576lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
577{
578 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000579 Error error;
580 valobj.GetData(data, error);
581
582 if (error.Fail())
583 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000584
585 std::string value;
586 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
587 if (!value.empty())
588 stream.Printf("%s ", value.c_str());
589
590 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
591}
592
593bool
594lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
595{
596 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000597 Error error;
598 valobj.GetData(data, error);
599
600 if (error.Fail())
601 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000602
603 std::string value;
604 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
605 if (!value.empty())
606 stream.Printf("%s ", value.c_str());
607
608 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
609}
610
611bool
612lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
613{
614 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000615 Error error;
616 valobj.GetData(data, error);
617
618 if (error.Fail())
619 return false;
Enrico Granata93d59662013-01-14 23:53:26 +0000620
Greg Clayton57ee3062013-07-11 22:46:58 +0000621 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
Enrico Granata93d59662013-01-14 23:53:26 +0000622
623 if (!ast)
624 return false;
625
Greg Clayton57ee3062013-07-11 22:46:58 +0000626 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
627 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata93d59662013-01-14 23:53:26 +0000628 std::string value;
629
Enrico Granata93d59662013-01-14 23:53:26 +0000630 switch (wchar_size)
631 {
632 case 8:
633 // utf 8
634 valobj.GetValueAsCString(lldb::eFormatChar, value);
635 if (!value.empty())
636 stream.Printf("%s ", value.c_str());
637 return DumpUTFBufferToStream<UTF8>(nullptr,
638 data,
639 stream,
640 'L',
641 '\'',
642 1);
643 case 16:
644 // utf 16
645 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
646 if (!value.empty())
647 stream.Printf("%s ", value.c_str());
648 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
649 data,
650 stream,
651 'L',
652 '\'',
653 1);
654 case 32:
655 // utf 32
656 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
657 if (!value.empty())
658 stream.Printf("%s ", value.c_str());
659 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
660 data,
661 stream,
662 'L',
663 '\'',
664 1);
Enrico Granata38352042013-01-11 02:44:00 +0000665 default:
666 stream.Printf("size for wchar_t is not valid");
667 return true;
668 }
669 return true;
Enrico Granataf68df122013-01-10 22:08:35 +0000670}
671
Enrico Granataa3962a72013-05-15 00:47:46 +0000672// the field layout in a libc++ string (cap, side, data or data, size, cap)
673enum LibcxxStringLayoutMode
674{
675 eLibcxxStringLayoutModeCSD = 0,
676 eLibcxxStringLayoutModeDSC = 1,
677 eLibcxxStringLayoutModeInvalid = 0xffff
678};
679
680// this function abstracts away the layout and mode details of a libc++ string
681// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000682static bool
683ExtractLibcxxStringInfo (ValueObject& valobj,
684 ValueObjectSP &location_sp,
685 uint64_t& size)
686{
687 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
688 if (!D)
689 return false;
690
Enrico Granataa3962a72013-05-15 00:47:46 +0000691 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
692
693 // this child should exist
694 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000695 return false;
696
Enrico Granataa3962a72013-05-15 00:47:46 +0000697 ConstString g_data_name("__data_");
698 ConstString g_size_name("__size_");
699 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
700 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
701 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000702
Enrico Granataa3962a72013-05-15 00:47:46 +0000703 if (layout == eLibcxxStringLayoutModeDSC)
704 {
705 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
706 if (!size_mode)
707 return false;
708
709 if (size_mode->GetName() != g_size_name)
710 {
711 // we are hitting the padding structure, move along
712 size_mode = D->GetChildAtIndexPath({1,1,1});
713 if (!size_mode)
714 return false;
715 }
716
717 size_mode_value = (size_mode->GetValueAsUnsigned(0));
718 short_mode = ((size_mode_value & 0x80) == 0);
719 }
720 else
721 {
722 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
723 if (!size_mode)
724 return false;
725
726 size_mode_value = (size_mode->GetValueAsUnsigned(0));
727 short_mode = ((size_mode_value & 1) == 0);
728 }
729
730 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000731 {
732 ValueObjectSP s(D->GetChildAtIndex(1, true));
733 if (!s)
734 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000735 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
736 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000737 return (location_sp.get() != nullptr);
738 }
739 else
740 {
741 ValueObjectSP l(D->GetChildAtIndex(0, true));
742 if (!l)
743 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000744 // we can use the layout_decider object as the data pointer
745 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000746 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
747 if (!size_vo || !location_sp)
748 return false;
749 size = size_vo->GetValueAsUnsigned(0);
750 return true;
751 }
752}
753
754bool
755lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
756{
757 uint64_t size = 0;
758 ValueObjectSP location_sp((ValueObject*)nullptr);
759 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
760 return false;
761 if (size == 0)
762 {
763 stream.Printf("L\"\"");
764 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000765 }
Enrico Granata3309d882013-01-12 01:00:22 +0000766 if (!location_sp)
767 return false;
768 return WCharStringSummaryProvider(*location_sp.get(), stream);
769}
770
771bool
772lldb_private::formatters::LibcxxStringSummaryProvider (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("\"\"");
781 return true;
782 }
783 if (!location_sp)
784 return false;
785 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000786 if (location_sp->ReadPointedString(stream,
787 error,
788 0, // max length is decided by the settings
789 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
790 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000791 return error.Success();
792}
793
Enrico Granata55900862013-03-15 18:55:30 +0000794bool
795lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
796{
797 ProcessSP process_sp = valobj.GetProcessSP();
798 if (!process_sp)
799 return false;
800
801 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
802
803 if (!runtime)
804 return false;
805
Greg Clayton03da4cc2013-04-19 21:31:16 +0000806 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000807
808 if (!descriptor.get() || !descriptor->IsValid())
809 return false;
810
811 const char* class_name = descriptor->GetClassName().GetCString();
812
813 if (!class_name || !*class_name)
814 return false;
815
816 stream.Printf("%s",class_name);
817 return true;
818}
819
Enrico Granatac76b97b2013-04-26 00:59:02 +0000820class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
821{
822public:
823 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
824 SyntheticChildrenFrontEnd(*valobj_sp.get())
825 {
826 }
827
828 virtual size_t
829 CalculateNumChildren ()
830 {
831 return 0;
832 }
833
834 virtual lldb::ValueObjectSP
835 GetChildAtIndex (size_t idx)
836 {
837 return lldb::ValueObjectSP();
838 }
839
840 virtual bool
841 Update()
842 {
843 return false;
844 }
845
846 virtual bool
847 MightHaveChildren ()
848 {
849 return false;
850 }
851
852 virtual size_t
853 GetIndexOfChildWithName (const ConstString &name)
854 {
855 return UINT32_MAX;
856 }
857
858 virtual
859 ~ObjCClassSyntheticChildrenFrontEnd ()
860 {
861 }
862};
863
864SyntheticChildrenFrontEnd*
865lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
866{
867 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
868}
869
Enrico Granataf5196282012-09-04 18:48:21 +0000870template<bool needs_at>
871bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000872lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000873{
874 ProcessSP process_sp = valobj.GetProcessSP();
875 if (!process_sp)
876 return false;
877
878 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
879
880 if (!runtime)
881 return false;
882
883 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
884
885 if (!descriptor.get() || !descriptor->IsValid())
886 return false;
887
888 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
889 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
890
891 if (!valobj_addr)
892 return false;
893
894 uint64_t value = 0;
895
896 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000897
898 if (!class_name || !*class_name)
899 return false;
900
Enrico Granataf5196282012-09-04 18:48:21 +0000901 if (!strcmp(class_name,"NSConcreteData") ||
902 !strcmp(class_name,"NSConcreteMutableData") ||
903 !strcmp(class_name,"__NSCFData"))
904 {
905 uint32_t offset = (is_64bit ? 16 : 8);
906 Error error;
907 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
908 if (error.Fail())
909 return false;
910 }
911 else
912 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000913 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000914 return false;
915 }
916
Daniel Malead01b2952012-11-29 21:49:15 +0000917 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000918 (needs_at ? "@\"" : ""),
919 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000920 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000921 (needs_at ? "\"" : ""));
922
923 return true;
924}
925
Enrico Granata87f00b42013-02-21 20:31:18 +0000926static bool
927ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
928 lldb::ProcessSP& process_sp,
929 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000930 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000931 Error* error = NULL,
932 size_t *data_read = NULL,
933 char prefix_token = '@',
934 char quote = '"')
935{
936 Error my_error;
937 size_t my_data_read;
938 if (!process_sp || location == 0)
939 return false;
940
Enrico Granata23ab35a2013-04-02 23:07:55 +0000941 if (!size)
942 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
943 else
944 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000945
946 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
947
948 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
949
950 if (error)
951 *error = my_error;
952 if (data_read)
953 *data_read = my_data_read;
954
955 if (my_error.Fail())
956 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000957
958 dest.Printf("%c%c",prefix_token,quote);
959
Enrico Granata87f00b42013-02-21 20:31:18 +0000960 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000961 dest.Printf("%s",(char*)buffer_sp->GetBytes());
962
963 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000964
965 return true;
966}
967
Enrico Granataf5196282012-09-04 18:48:21 +0000968bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000969lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000970{
971 ProcessSP process_sp = valobj.GetProcessSP();
972 if (!process_sp)
973 return false;
974
975 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
976
977 if (!runtime)
978 return false;
979
980 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
981
982 if (!descriptor.get() || !descriptor->IsValid())
983 return false;
984
985 uint32_t ptr_size = process_sp->GetAddressByteSize();
986
987 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
988
989 if (!valobj_addr)
990 return false;
991
992 const char* class_name = descriptor->GetClassName().GetCString();
993
Enrico Granata60b81df2012-09-29 00:45:53 +0000994 if (!class_name || !*class_name)
995 return false;
996
Enrico Granataf5196282012-09-04 18:48:21 +0000997 uint64_t info_bits_location = valobj_addr + ptr_size;
998 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
999 info_bits_location += 3;
1000
Enrico Granata87f00b42013-02-21 20:31:18 +00001001 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +00001002
1003 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
1004 if (error.Fail())
1005 return false;
1006
1007 bool is_mutable = (info_bits & 1) == 1;
1008 bool is_inline = (info_bits & 0x60) == 0;
1009 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
1010 bool is_unicode = (info_bits & 0x10) == 0x10;
1011 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001012 bool has_null = (info_bits & 8) == 8;
1013
1014 size_t explicit_length = 0;
1015 if (!has_null && has_explicit_length && !is_special)
1016 {
1017 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001018 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001019 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1020 else if (is_inline)
1021 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001022 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001023 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1024 else
1025 explicit_length_offset = 0;
1026
1027 if (explicit_length_offset)
1028 {
1029 explicit_length_offset = valobj_addr + explicit_length_offset;
1030 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1031 }
1032 }
1033
Enrico Granataf5196282012-09-04 18:48:21 +00001034 if (strcmp(class_name,"NSString") &&
1035 strcmp(class_name,"CFStringRef") &&
1036 strcmp(class_name,"CFMutableStringRef") &&
1037 strcmp(class_name,"__NSCFConstantString") &&
1038 strcmp(class_name,"__NSCFString") &&
1039 strcmp(class_name,"NSCFConstantString") &&
1040 strcmp(class_name,"NSCFString") &&
1041 strcmp(class_name,"NSPathStore2"))
1042 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001043 // not one of us - but tell me class name
1044 stream.Printf("class name = %s",class_name);
1045 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001046 }
1047
1048 if (is_mutable)
1049 {
1050 uint64_t location = 2 * ptr_size + valobj_addr;
1051 location = process_sp->ReadPointerFromMemory(location, error);
1052 if (error.Fail())
1053 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001054 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001055 {
1056 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1057 options.SetConversionFunction(ConvertUTF16toUTF8);
1058 options.SetLocation(location);
1059 options.SetProcessSP(process_sp);
1060 options.SetStream(&stream);
1061 options.SetPrefixToken('@');
1062 options.SetQuote('"');
1063 options.SetSourceSize(explicit_length);
1064 options.SetNeedsZeroTermination(false);
1065 return ReadUTFBufferAndDumpToStream (options);
1066 }
Enrico Granataf5196282012-09-04 18:48:21 +00001067 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001068 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001069 }
1070 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1071 {
1072 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001073 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001074 }
1075 else if (is_unicode)
1076 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001077 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001078 if (is_inline)
1079 {
1080 if (!has_explicit_length)
1081 {
1082 stream.Printf("found new combo");
1083 return true;
1084 }
1085 else
1086 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001087 }
Enrico Granataf5196282012-09-04 18:48:21 +00001088 else
1089 {
1090 location = process_sp->ReadPointerFromMemory(location, error);
1091 if (error.Fail())
1092 return false;
1093 }
Enrico Granata56768392013-04-23 20:05:05 +00001094 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1095 options.SetConversionFunction(ConvertUTF16toUTF8);
1096 options.SetLocation(location);
1097 options.SetProcessSP(process_sp);
1098 options.SetStream(&stream);
1099 options.SetPrefixToken('@');
1100 options.SetQuote('"');
1101 options.SetSourceSize(explicit_length);
1102 options.SetNeedsZeroTermination(has_explicit_length == false);
1103 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001104 }
1105 else if (is_special)
1106 {
1107 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001108 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1109 options.SetConversionFunction(ConvertUTF16toUTF8);
1110 options.SetLocation(location);
1111 options.SetProcessSP(process_sp);
1112 options.SetStream(&stream);
1113 options.SetPrefixToken('@');
1114 options.SetQuote('"');
1115 options.SetSourceSize(explicit_length);
1116 options.SetNeedsZeroTermination(has_explicit_length == false);
1117 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001118 }
1119 else if (is_inline)
1120 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001121 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001122 if (!has_explicit_length)
1123 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001124 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001125 }
1126 else
1127 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001128 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001129 location = process_sp->ReadPointerFromMemory(location, error);
1130 if (error.Fail())
1131 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +00001132 if (has_explicit_length && !has_null)
1133 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 +00001134 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001135 }
1136
1137 stream.Printf("class name = %s",class_name);
1138 return true;
1139
1140}
1141
Enrico Granataf175ad12012-10-03 23:53:45 +00001142bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001143lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1144{
1145 TargetSP target_sp(valobj.GetTargetSP());
1146 if (!target_sp)
1147 return false;
1148 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001149 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1150 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001151 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001152 pointer_value += addr_size;
1153 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001154 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001155 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001156 if (!child_ptr_sp)
1157 return false;
1158 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001159 Error error;
1160 child_ptr_sp->GetData(data, error);
1161 if (error.Fail())
1162 return false;
Enrico Granata5bfce362013-02-08 01:55:46 +00001163 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1164 child_sp->GetValueAsUnsigned(0);
1165 if (child_sp)
1166 return NSStringSummaryProvider(*child_sp, stream);
1167 return false;
1168}
1169
1170bool
1171lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1172{
1173 return NSAttributedStringSummaryProvider(valobj, stream);
1174}
1175
1176bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001177lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1178{
1179 stream.Printf("%s",valobj.GetObjectDescription());
1180 return true;
1181}
1182
Enrico Granatab5887262012-10-29 21:18:03 +00001183bool
1184lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1185{
Greg Clayton57ee3062013-07-11 22:46:58 +00001186 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001187
1188 ValueObjectSP real_guy_sp = valobj.GetSP();
1189
Greg Clayton57ee3062013-07-11 22:46:58 +00001190 if (type_info & ClangASTType::eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001191 {
1192 Error err;
1193 real_guy_sp = valobj.Dereference(err);
1194 if (err.Fail() || !real_guy_sp)
1195 return false;
1196 }
Greg Clayton57ee3062013-07-11 22:46:58 +00001197 else if (type_info & ClangASTType::eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001198 {
1199 real_guy_sp = valobj.GetChildAtIndex(0, true);
1200 if (!real_guy_sp)
1201 return false;
1202 }
1203 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1204 if (value == 0)
1205 {
1206 stream.Printf("NO");
1207 return true;
1208 }
1209 stream.Printf("YES");
1210 return true;
1211}
1212
1213template <bool is_sel_ptr>
1214bool
1215lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1216{
Enrico Granata75dfb432013-02-15 00:06:04 +00001217 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001218
Greg Clayton57ee3062013-07-11 22:46:58 +00001219 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1220
1221 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001222 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001223
Enrico Granatab5887262012-10-29 21:18:03 +00001224 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1225
Enrico Granata75dfb432013-02-15 00:06:04 +00001226 if (is_sel_ptr)
1227 {
1228 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1229 if (data_address == LLDB_INVALID_ADDRESS)
1230 return false;
1231 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1232 }
1233 else
1234 {
1235 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +00001236 Error error;
1237 valobj.GetData(data, error);
1238 if (error.Fail())
1239 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001240 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1241 }
Enrico Granatab5887262012-10-29 21:18:03 +00001242
Enrico Granata75dfb432013-02-15 00:06:04 +00001243 if (!valobj_sp)
1244 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001245
1246 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1247 return true;
1248}
1249
Enrico Granata6d37cc62013-03-19 00:27:22 +00001250// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1251// this call gives the POSIX equivalent of the Cocoa epoch
1252time_t
Enrico Granata92373532013-03-19 22:58:48 +00001253lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001254{
1255 static time_t epoch = 0;
1256 if (!epoch)
1257 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001258#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001259 tzset();
1260 tm tm_epoch;
1261 tm_epoch.tm_sec = 0;
1262 tm_epoch.tm_hour = 0;
1263 tm_epoch.tm_min = 0;
1264 tm_epoch.tm_mon = 0;
1265 tm_epoch.tm_mday = 1;
1266 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1267 tm_epoch.tm_isdst = -1;
1268 tm_epoch.tm_gmtoff = 0;
1269 tm_epoch.tm_zone = NULL;
1270 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001271#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001272 }
1273 return epoch;
1274}
1275
Greg Claytonc7bece562013-01-25 18:06:21 +00001276size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001277lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001278{
1279 if (!item_name || !*item_name)
1280 return UINT32_MAX;
1281 if (*item_name != '[')
1282 return UINT32_MAX;
1283 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001284 char* endptr = NULL;
1285 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1286 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001287 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001288 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001289 return UINT32_MAX;
1290 return idx;
1291}
1292
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001293lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1294 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001295SyntheticChildrenFrontEnd(*valobj_sp.get()),
1296m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001297m_item_name(item_name),
1298m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001299{
1300 if (valobj_sp)
1301 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001302}
1303
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001304bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001305lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001306{
Enrico Granata6eca3552013-03-28 18:50:54 +00001307 m_item_sp.reset();
1308
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001309 ValueObjectSP valobj_sp = m_backend.GetSP();
1310 if (!valobj_sp)
1311 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001312
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001313 if (!valobj_sp)
1314 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001315
1316 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1317 if (!item_ptr)
1318 return false;
1319 if (item_ptr->GetValueAsUnsigned(0) == 0)
1320 return false;
1321 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001322 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Greg Clayton57ee3062013-07-11 22:46:58 +00001323 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 +00001324 if (err.Fail())
1325 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001326 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001327}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001328
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001329size_t
1330lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1331{
1332 return 1;
1333}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001334
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001335lldb::ValueObjectSP
1336lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1337{
1338 if (idx == 0)
1339 return m_item_sp;
1340 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001341}
1342
1343bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001344lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001345{
1346 return true;
1347}
1348
1349size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001350lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001351{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001352 if (name == ConstString("item"))
1353 return 0;
1354 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001355}
1356
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001357lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001358{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001359}
1360
Enrico Granataf5196282012-09-04 18:48:21 +00001361template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001362lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1363
1364template bool
1365lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001366
1367template bool
1368lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1369
1370template bool
1371lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;