blob: 136c8c51e660aed72dd37cad25d97aa16bd45437 [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;
579 valobj.GetData(data);
580
581 std::string value;
582 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
583 if (!value.empty())
584 stream.Printf("%s ", value.c_str());
585
586 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
587}
588
589bool
590lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
591{
592 DataExtractor data;
593 valobj.GetData(data);
594
595 std::string value;
596 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
597 if (!value.empty())
598 stream.Printf("%s ", value.c_str());
599
600 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
601}
602
603bool
604lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
605{
606 DataExtractor data;
607 valobj.GetData(data);
608
Greg Clayton57ee3062013-07-11 22:46:58 +0000609 clang::ASTContext* ast = valobj.GetClangType().GetASTContext();
Enrico Granata93d59662013-01-14 23:53:26 +0000610
611 if (!ast)
612 return false;
613
Greg Clayton57ee3062013-07-11 22:46:58 +0000614 ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar);
615 const uint32_t wchar_size = wchar_clang_type.GetBitSize();
Enrico Granata93d59662013-01-14 23:53:26 +0000616 std::string value;
617
Enrico Granata93d59662013-01-14 23:53:26 +0000618 switch (wchar_size)
619 {
620 case 8:
621 // utf 8
622 valobj.GetValueAsCString(lldb::eFormatChar, value);
623 if (!value.empty())
624 stream.Printf("%s ", value.c_str());
625 return DumpUTFBufferToStream<UTF8>(nullptr,
626 data,
627 stream,
628 'L',
629 '\'',
630 1);
631 case 16:
632 // utf 16
633 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
634 if (!value.empty())
635 stream.Printf("%s ", value.c_str());
636 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
637 data,
638 stream,
639 'L',
640 '\'',
641 1);
642 case 32:
643 // utf 32
644 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
645 if (!value.empty())
646 stream.Printf("%s ", value.c_str());
647 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
648 data,
649 stream,
650 'L',
651 '\'',
652 1);
Enrico Granata38352042013-01-11 02:44:00 +0000653 default:
654 stream.Printf("size for wchar_t is not valid");
655 return true;
656 }
657 return true;
Enrico Granataf68df122013-01-10 22:08:35 +0000658}
659
Enrico Granataa3962a72013-05-15 00:47:46 +0000660// the field layout in a libc++ string (cap, side, data or data, size, cap)
661enum LibcxxStringLayoutMode
662{
663 eLibcxxStringLayoutModeCSD = 0,
664 eLibcxxStringLayoutModeDSC = 1,
665 eLibcxxStringLayoutModeInvalid = 0xffff
666};
667
668// this function abstracts away the layout and mode details of a libc++ string
669// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000670static bool
671ExtractLibcxxStringInfo (ValueObject& valobj,
672 ValueObjectSP &location_sp,
673 uint64_t& size)
674{
675 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
676 if (!D)
677 return false;
678
Enrico Granataa3962a72013-05-15 00:47:46 +0000679 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
680
681 // this child should exist
682 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000683 return false;
684
Enrico Granataa3962a72013-05-15 00:47:46 +0000685 ConstString g_data_name("__data_");
686 ConstString g_size_name("__size_");
687 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
688 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
689 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000690
Enrico Granataa3962a72013-05-15 00:47:46 +0000691 if (layout == eLibcxxStringLayoutModeDSC)
692 {
693 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
694 if (!size_mode)
695 return false;
696
697 if (size_mode->GetName() != g_size_name)
698 {
699 // we are hitting the padding structure, move along
700 size_mode = D->GetChildAtIndexPath({1,1,1});
701 if (!size_mode)
702 return false;
703 }
704
705 size_mode_value = (size_mode->GetValueAsUnsigned(0));
706 short_mode = ((size_mode_value & 0x80) == 0);
707 }
708 else
709 {
710 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
711 if (!size_mode)
712 return false;
713
714 size_mode_value = (size_mode->GetValueAsUnsigned(0));
715 short_mode = ((size_mode_value & 1) == 0);
716 }
717
718 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000719 {
720 ValueObjectSP s(D->GetChildAtIndex(1, true));
721 if (!s)
722 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000723 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
724 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000725 return (location_sp.get() != nullptr);
726 }
727 else
728 {
729 ValueObjectSP l(D->GetChildAtIndex(0, true));
730 if (!l)
731 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000732 // we can use the layout_decider object as the data pointer
733 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000734 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
735 if (!size_vo || !location_sp)
736 return false;
737 size = size_vo->GetValueAsUnsigned(0);
738 return true;
739 }
740}
741
742bool
743lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
744{
745 uint64_t size = 0;
746 ValueObjectSP location_sp((ValueObject*)nullptr);
747 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
748 return false;
749 if (size == 0)
750 {
751 stream.Printf("L\"\"");
752 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000753 }
Enrico Granata3309d882013-01-12 01:00:22 +0000754 if (!location_sp)
755 return false;
756 return WCharStringSummaryProvider(*location_sp.get(), stream);
757}
758
759bool
760lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
761{
762 uint64_t size = 0;
763 ValueObjectSP location_sp((ValueObject*)nullptr);
764 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
765 return false;
766 if (size == 0)
767 {
768 stream.Printf("\"\"");
769 return true;
770 }
771 if (!location_sp)
772 return false;
773 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000774 if (location_sp->ReadPointedString(stream,
775 error,
776 0, // max length is decided by the settings
777 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
778 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000779 return error.Success();
780}
781
Enrico Granata55900862013-03-15 18:55:30 +0000782bool
783lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
784{
785 ProcessSP process_sp = valobj.GetProcessSP();
786 if (!process_sp)
787 return false;
788
789 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
790
791 if (!runtime)
792 return false;
793
Greg Clayton03da4cc2013-04-19 21:31:16 +0000794 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000795
796 if (!descriptor.get() || !descriptor->IsValid())
797 return false;
798
799 const char* class_name = descriptor->GetClassName().GetCString();
800
801 if (!class_name || !*class_name)
802 return false;
803
804 stream.Printf("%s",class_name);
805 return true;
806}
807
Enrico Granatac76b97b2013-04-26 00:59:02 +0000808class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
809{
810public:
811 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
812 SyntheticChildrenFrontEnd(*valobj_sp.get())
813 {
814 }
815
816 virtual size_t
817 CalculateNumChildren ()
818 {
819 return 0;
820 }
821
822 virtual lldb::ValueObjectSP
823 GetChildAtIndex (size_t idx)
824 {
825 return lldb::ValueObjectSP();
826 }
827
828 virtual bool
829 Update()
830 {
831 return false;
832 }
833
834 virtual bool
835 MightHaveChildren ()
836 {
837 return false;
838 }
839
840 virtual size_t
841 GetIndexOfChildWithName (const ConstString &name)
842 {
843 return UINT32_MAX;
844 }
845
846 virtual
847 ~ObjCClassSyntheticChildrenFrontEnd ()
848 {
849 }
850};
851
852SyntheticChildrenFrontEnd*
853lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
854{
855 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
856}
857
Enrico Granataf5196282012-09-04 18:48:21 +0000858template<bool needs_at>
859bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000860lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000861{
862 ProcessSP process_sp = valobj.GetProcessSP();
863 if (!process_sp)
864 return false;
865
866 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
867
868 if (!runtime)
869 return false;
870
871 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
872
873 if (!descriptor.get() || !descriptor->IsValid())
874 return false;
875
876 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
877 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
878
879 if (!valobj_addr)
880 return false;
881
882 uint64_t value = 0;
883
884 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000885
886 if (!class_name || !*class_name)
887 return false;
888
Enrico Granataf5196282012-09-04 18:48:21 +0000889 if (!strcmp(class_name,"NSConcreteData") ||
890 !strcmp(class_name,"NSConcreteMutableData") ||
891 !strcmp(class_name,"__NSCFData"))
892 {
893 uint32_t offset = (is_64bit ? 16 : 8);
894 Error error;
895 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
896 if (error.Fail())
897 return false;
898 }
899 else
900 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000901 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000902 return false;
903 }
904
Daniel Malead01b2952012-11-29 21:49:15 +0000905 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000906 (needs_at ? "@\"" : ""),
907 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000908 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000909 (needs_at ? "\"" : ""));
910
911 return true;
912}
913
Enrico Granata87f00b42013-02-21 20:31:18 +0000914static bool
915ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
916 lldb::ProcessSP& process_sp,
917 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000918 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000919 Error* error = NULL,
920 size_t *data_read = NULL,
921 char prefix_token = '@',
922 char quote = '"')
923{
924 Error my_error;
925 size_t my_data_read;
926 if (!process_sp || location == 0)
927 return false;
928
Enrico Granata23ab35a2013-04-02 23:07:55 +0000929 if (!size)
930 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
931 else
932 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000933
934 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
935
936 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
937
938 if (error)
939 *error = my_error;
940 if (data_read)
941 *data_read = my_data_read;
942
943 if (my_error.Fail())
944 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000945
946 dest.Printf("%c%c",prefix_token,quote);
947
Enrico Granata87f00b42013-02-21 20:31:18 +0000948 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000949 dest.Printf("%s",(char*)buffer_sp->GetBytes());
950
951 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000952
953 return true;
954}
955
Enrico Granataf5196282012-09-04 18:48:21 +0000956bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000957lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000958{
959 ProcessSP process_sp = valobj.GetProcessSP();
960 if (!process_sp)
961 return false;
962
963 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
964
965 if (!runtime)
966 return false;
967
968 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
969
970 if (!descriptor.get() || !descriptor->IsValid())
971 return false;
972
973 uint32_t ptr_size = process_sp->GetAddressByteSize();
974
975 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
976
977 if (!valobj_addr)
978 return false;
979
980 const char* class_name = descriptor->GetClassName().GetCString();
981
Enrico Granata60b81df2012-09-29 00:45:53 +0000982 if (!class_name || !*class_name)
983 return false;
984
Enrico Granataf5196282012-09-04 18:48:21 +0000985 uint64_t info_bits_location = valobj_addr + ptr_size;
986 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
987 info_bits_location += 3;
988
Enrico Granata87f00b42013-02-21 20:31:18 +0000989 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000990
991 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
992 if (error.Fail())
993 return false;
994
995 bool is_mutable = (info_bits & 1) == 1;
996 bool is_inline = (info_bits & 0x60) == 0;
997 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
998 bool is_unicode = (info_bits & 0x10) == 0x10;
999 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001000 bool has_null = (info_bits & 8) == 8;
1001
1002 size_t explicit_length = 0;
1003 if (!has_null && has_explicit_length && !is_special)
1004 {
1005 lldb::addr_t explicit_length_offset = 2*ptr_size;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001006 if (is_mutable && !is_inline)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001007 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1008 else if (is_inline)
1009 explicit_length = explicit_length + 0; // inline1.length;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001010 else if (!is_inline && !is_mutable)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001011 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1012 else
1013 explicit_length_offset = 0;
1014
1015 if (explicit_length_offset)
1016 {
1017 explicit_length_offset = valobj_addr + explicit_length_offset;
1018 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1019 }
1020 }
1021
Enrico Granataf5196282012-09-04 18:48:21 +00001022 if (strcmp(class_name,"NSString") &&
1023 strcmp(class_name,"CFStringRef") &&
1024 strcmp(class_name,"CFMutableStringRef") &&
1025 strcmp(class_name,"__NSCFConstantString") &&
1026 strcmp(class_name,"__NSCFString") &&
1027 strcmp(class_name,"NSCFConstantString") &&
1028 strcmp(class_name,"NSCFString") &&
1029 strcmp(class_name,"NSPathStore2"))
1030 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001031 // not one of us - but tell me class name
1032 stream.Printf("class name = %s",class_name);
1033 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001034 }
1035
1036 if (is_mutable)
1037 {
1038 uint64_t location = 2 * ptr_size + valobj_addr;
1039 location = process_sp->ReadPointerFromMemory(location, error);
1040 if (error.Fail())
1041 return false;
Virgile Bellof02a3c52013-08-27 16:24:58 +00001042 if (has_explicit_length && is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001043 {
1044 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1045 options.SetConversionFunction(ConvertUTF16toUTF8);
1046 options.SetLocation(location);
1047 options.SetProcessSP(process_sp);
1048 options.SetStream(&stream);
1049 options.SetPrefixToken('@');
1050 options.SetQuote('"');
1051 options.SetSourceSize(explicit_length);
1052 options.SetNeedsZeroTermination(false);
1053 return ReadUTFBufferAndDumpToStream (options);
1054 }
Enrico Granataf5196282012-09-04 18:48:21 +00001055 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001056 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001057 }
1058 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1059 {
1060 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001061 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001062 }
1063 else if (is_unicode)
1064 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001065 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001066 if (is_inline)
1067 {
1068 if (!has_explicit_length)
1069 {
1070 stream.Printf("found new combo");
1071 return true;
1072 }
1073 else
1074 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001075 }
Enrico Granataf5196282012-09-04 18:48:21 +00001076 else
1077 {
1078 location = process_sp->ReadPointerFromMemory(location, error);
1079 if (error.Fail())
1080 return false;
1081 }
Enrico Granata56768392013-04-23 20:05:05 +00001082 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1083 options.SetConversionFunction(ConvertUTF16toUTF8);
1084 options.SetLocation(location);
1085 options.SetProcessSP(process_sp);
1086 options.SetStream(&stream);
1087 options.SetPrefixToken('@');
1088 options.SetQuote('"');
1089 options.SetSourceSize(explicit_length);
1090 options.SetNeedsZeroTermination(has_explicit_length == false);
1091 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001092 }
1093 else if (is_special)
1094 {
1095 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001096 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1097 options.SetConversionFunction(ConvertUTF16toUTF8);
1098 options.SetLocation(location);
1099 options.SetProcessSP(process_sp);
1100 options.SetStream(&stream);
1101 options.SetPrefixToken('@');
1102 options.SetQuote('"');
1103 options.SetSourceSize(explicit_length);
1104 options.SetNeedsZeroTermination(has_explicit_length == false);
1105 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001106 }
1107 else if (is_inline)
1108 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001109 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001110 if (!has_explicit_length)
1111 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001112 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001113 }
1114 else
1115 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001116 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001117 location = process_sp->ReadPointerFromMemory(location, error);
1118 if (error.Fail())
1119 return false;
Enrico Granatac71f3492013-06-19 19:15:29 +00001120 if (has_explicit_length && !has_null)
1121 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 +00001122 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001123 }
1124
1125 stream.Printf("class name = %s",class_name);
1126 return true;
1127
1128}
1129
Enrico Granataf175ad12012-10-03 23:53:45 +00001130bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001131lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1132{
1133 TargetSP target_sp(valobj.GetTargetSP());
1134 if (!target_sp)
1135 return false;
1136 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
Greg Clayton57ee3062013-07-11 22:46:58 +00001137 uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
1138 if (!pointer_value)
Enrico Granata5bfce362013-02-08 01:55:46 +00001139 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +00001140 pointer_value += addr_size;
1141 ClangASTType type(valobj.GetClangType());
Enrico Granata5bfce362013-02-08 01:55:46 +00001142 ExecutionContext exe_ctx(target_sp,false);
Greg Clayton57ee3062013-07-11 22:46:58 +00001143 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
Enrico Granata5bfce362013-02-08 01:55:46 +00001144 if (!child_ptr_sp)
1145 return false;
1146 DataExtractor data;
1147 child_ptr_sp->GetData(data);
1148 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1149 child_sp->GetValueAsUnsigned(0);
1150 if (child_sp)
1151 return NSStringSummaryProvider(*child_sp, stream);
1152 return false;
1153}
1154
1155bool
1156lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1157{
1158 return NSAttributedStringSummaryProvider(valobj, stream);
1159}
1160
1161bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001162lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1163{
1164 stream.Printf("%s",valobj.GetObjectDescription());
1165 return true;
1166}
1167
Enrico Granatab5887262012-10-29 21:18:03 +00001168bool
1169lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1170{
Greg Clayton57ee3062013-07-11 22:46:58 +00001171 const uint32_t type_info = valobj.GetClangType().GetTypeInfo();
Enrico Granatab5887262012-10-29 21:18:03 +00001172
1173 ValueObjectSP real_guy_sp = valobj.GetSP();
1174
Greg Clayton57ee3062013-07-11 22:46:58 +00001175 if (type_info & ClangASTType::eTypeIsPointer)
Enrico Granatab5887262012-10-29 21:18:03 +00001176 {
1177 Error err;
1178 real_guy_sp = valobj.Dereference(err);
1179 if (err.Fail() || !real_guy_sp)
1180 return false;
1181 }
Greg Clayton57ee3062013-07-11 22:46:58 +00001182 else if (type_info & ClangASTType::eTypeIsReference)
Enrico Granatab5887262012-10-29 21:18:03 +00001183 {
1184 real_guy_sp = valobj.GetChildAtIndex(0, true);
1185 if (!real_guy_sp)
1186 return false;
1187 }
1188 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1189 if (value == 0)
1190 {
1191 stream.Printf("NO");
1192 return true;
1193 }
1194 stream.Printf("YES");
1195 return true;
1196}
1197
1198template <bool is_sel_ptr>
1199bool
1200lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1201{
Enrico Granata75dfb432013-02-15 00:06:04 +00001202 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001203
Greg Clayton57ee3062013-07-11 22:46:58 +00001204 ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
1205
1206 if (!charstar)
Enrico Granatab5887262012-10-29 21:18:03 +00001207 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001208
Enrico Granatab5887262012-10-29 21:18:03 +00001209 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1210
Enrico Granata75dfb432013-02-15 00:06:04 +00001211 if (is_sel_ptr)
1212 {
1213 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1214 if (data_address == LLDB_INVALID_ADDRESS)
1215 return false;
1216 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1217 }
1218 else
1219 {
1220 DataExtractor data;
1221 valobj.GetData(data);
1222 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1223 }
Enrico Granatab5887262012-10-29 21:18:03 +00001224
Enrico Granata75dfb432013-02-15 00:06:04 +00001225 if (!valobj_sp)
1226 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001227
1228 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1229 return true;
1230}
1231
Enrico Granata6d37cc62013-03-19 00:27:22 +00001232// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1233// this call gives the POSIX equivalent of the Cocoa epoch
1234time_t
Enrico Granata92373532013-03-19 22:58:48 +00001235lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001236{
1237 static time_t epoch = 0;
1238 if (!epoch)
1239 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001240#ifndef _WIN32
Enrico Granata6d37cc62013-03-19 00:27:22 +00001241 tzset();
1242 tm tm_epoch;
1243 tm_epoch.tm_sec = 0;
1244 tm_epoch.tm_hour = 0;
1245 tm_epoch.tm_min = 0;
1246 tm_epoch.tm_mon = 0;
1247 tm_epoch.tm_mday = 1;
1248 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1249 tm_epoch.tm_isdst = -1;
1250 tm_epoch.tm_gmtoff = 0;
1251 tm_epoch.tm_zone = NULL;
1252 epoch = timegm(&tm_epoch);
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001253#endif
Enrico Granata6d37cc62013-03-19 00:27:22 +00001254 }
1255 return epoch;
1256}
1257
Greg Claytonc7bece562013-01-25 18:06:21 +00001258size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001259lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001260{
1261 if (!item_name || !*item_name)
1262 return UINT32_MAX;
1263 if (*item_name != '[')
1264 return UINT32_MAX;
1265 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001266 char* endptr = NULL;
1267 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1268 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001269 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001270 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001271 return UINT32_MAX;
1272 return idx;
1273}
1274
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001275lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1276 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001277SyntheticChildrenFrontEnd(*valobj_sp.get()),
1278m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001279m_item_name(item_name),
1280m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001281{
1282 if (valobj_sp)
1283 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001284}
1285
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001286bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001287lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001288{
Enrico Granata6eca3552013-03-28 18:50:54 +00001289 m_item_sp.reset();
1290
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001291 ValueObjectSP valobj_sp = m_backend.GetSP();
1292 if (!valobj_sp)
1293 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001294
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001295 if (!valobj_sp)
1296 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001297
1298 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1299 if (!item_ptr)
1300 return false;
1301 if (item_ptr->GetValueAsUnsigned(0) == 0)
1302 return false;
1303 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001304 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Greg Clayton57ee3062013-07-11 22:46:58 +00001305 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 +00001306 if (err.Fail())
1307 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001308 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001309}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001310
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001311size_t
1312lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1313{
1314 return 1;
1315}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001316
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001317lldb::ValueObjectSP
1318lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1319{
1320 if (idx == 0)
1321 return m_item_sp;
1322 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001323}
1324
1325bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001326lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001327{
1328 return true;
1329}
1330
1331size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001332lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001333{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001334 if (name == ConstString("item"))
1335 return 0;
1336 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001337}
1338
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001339lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001340{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001341}
1342
Enrico Granataf5196282012-09-04 18:48:21 +00001343template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001344lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1345
1346template bool
1347lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001348
1349template bool
1350lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1351
1352template bool
1353lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;