blob: 69e2f6a04dab23026f58119d27e79fbf472771df [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
Enrico Granata5548cb52013-01-28 23:47:25 +000010#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granataf5196282012-09-04 18:48:21 +000011
Dmitri Gribenko024aa852013-01-30 15:05:59 +000012#include "llvm/Support/ConvertUTF.h"
Enrico Granataf5196282012-09-04 18:48:21 +000013
Enrico Granatab2698cd2012-09-13 18:27:09 +000014#include "lldb/Core/DataBufferHeap.h"
15#include "lldb/Core/Error.h"
Enrico Granataf5196282012-09-04 18:48:21 +000016#include "lldb/Core/Stream.h"
17#include "lldb/Core/ValueObject.h"
Enrico Granatab2698cd2012-09-13 18:27:09 +000018#include "lldb/Core/ValueObjectConstResult.h"
19#include "lldb/Host/Endian.h"
Enrico Granatab5887262012-10-29 21:18:03 +000020#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataf5196282012-09-04 18:48:21 +000021#include "lldb/Target/ObjCLanguageRuntime.h"
22#include "lldb/Target/Target.h"
23
Enrico Granatad83bfce2013-04-02 21:25:34 +000024#include <algorithm>
25
Enrico Granataf5196282012-09-04 18:48:21 +000026using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
30bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000031lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
32 const char* target_type,
33 const char* selector,
34 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000035{
36 if (!target_type || !*target_type)
37 return false;
38 if (!selector || !*selector)
39 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000040 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000041 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000042 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
43 lldb::ValueObjectSP result_sp;
44 Target* target = exe_ctx.GetTargetPtr();
45 StackFrame* stack_frame = exe_ctx.GetFramePtr();
46 if (!target || !stack_frame)
47 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000048
Jim Ingham35e1bda2012-10-16 21:41:58 +000049 EvaluateExpressionOptions options;
Enrico Granatad4439aa2012-09-05 20:41:26 +000050 options.SetCoerceToId(false)
51 .SetUnwindOnError(true)
Sean Callananc7cb3142012-12-04 20:56:04 +000052 .SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000053
Enrico Granataf5196282012-09-04 18:48:21 +000054 target->EvaluateExpression(expr.GetData(),
55 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000056 result_sp,
57 options);
Enrico Granataf5196282012-09-04 18:48:21 +000058 if (!result_sp)
59 return false;
60 value = result_sp->GetValueAsUnsigned(0);
61 return true;
62}
63
Enrico Granataf615b802013-02-15 23:38:37 +000064bool
65lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
66 const char* target_type,
67 const char* selector,
68 Stream &stream)
69{
70 if (!target_type || !*target_type)
71 return false;
72 if (!selector || !*selector)
73 return false;
74 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +000075 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +000076 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
77 lldb::ValueObjectSP result_sp;
78 Target* target = exe_ctx.GetTargetPtr();
79 StackFrame* stack_frame = exe_ctx.GetFramePtr();
80 if (!target || !stack_frame)
81 return false;
82
83 EvaluateExpressionOptions options;
84 options.SetCoerceToId(false)
85 .SetUnwindOnError(true)
86 .SetKeepInMemory(true)
87 .SetUseDynamic(lldb::eDynamicCanRunTarget);
88
89 target->EvaluateExpression(expr.GetData(),
90 stack_frame,
91 result_sp,
92 options);
93 if (!result_sp)
94 return false;
95 stream.Printf("%s",result_sp->GetSummaryAsCString());
96 return true;
97}
98
Enrico Granatab2698cd2012-09-13 18:27:09 +000099lldb::ValueObjectSP
100lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
101 const char* return_type,
102 const char* selector,
103 uint64_t index)
104{
105 lldb::ValueObjectSP valobj_sp;
106 if (!return_type || !*return_type)
107 return valobj_sp;
108 if (!selector || !*selector)
109 return valobj_sp;
110 StreamString expr_path_stream;
111 valobj.GetExpressionPath(expr_path_stream, false);
112 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000113 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000114 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
115 lldb::ValueObjectSP result_sp;
116 Target* target = exe_ctx.GetTargetPtr();
117 StackFrame* stack_frame = exe_ctx.GetFramePtr();
118 if (!target || !stack_frame)
119 return valobj_sp;
120
Jim Ingham35e1bda2012-10-16 21:41:58 +0000121 EvaluateExpressionOptions options;
Enrico Granatab2698cd2012-09-13 18:27:09 +0000122 options.SetCoerceToId(false)
123 .SetUnwindOnError(true)
124 .SetKeepInMemory(true)
125 .SetUseDynamic(lldb::eDynamicCanRunTarget);
126
127 target->EvaluateExpression(expr.GetData(),
128 stack_frame,
129 valobj_sp,
130 options);
131 return valobj_sp;
132}
133
134lldb::ValueObjectSP
135lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
136 const char* return_type,
137 const char* selector,
138 const char* key)
139{
140 lldb::ValueObjectSP valobj_sp;
141 if (!return_type || !*return_type)
142 return valobj_sp;
143 if (!selector || !*selector)
144 return valobj_sp;
145 if (!key || !*key)
146 return valobj_sp;
147 StreamString expr_path_stream;
148 valobj.GetExpressionPath(expr_path_stream, false);
149 StreamString expr;
150 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
151 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
152 lldb::ValueObjectSP result_sp;
153 Target* target = exe_ctx.GetTargetPtr();
154 StackFrame* stack_frame = exe_ctx.GetFramePtr();
155 if (!target || !stack_frame)
156 return valobj_sp;
157
Jim Ingham35e1bda2012-10-16 21:41:58 +0000158 EvaluateExpressionOptions options;
Enrico Granatab2698cd2012-09-13 18:27:09 +0000159 options.SetCoerceToId(false)
160 .SetUnwindOnError(true)
161 .SetKeepInMemory(true)
162 .SetUseDynamic(lldb::eDynamicCanRunTarget);
163
164 target->EvaluateExpression(expr.GetData(),
165 stack_frame,
166 valobj_sp,
167 options);
168 return valobj_sp;
169}
170
Enrico Granata93d59662013-01-14 23:53:26 +0000171// use this call if you already have an LLDB-side buffer for the data
172template<typename SourceDataType>
Enrico Granataf68df122013-01-10 22:08:35 +0000173static bool
Enrico Granata93d59662013-01-14 23:53:26 +0000174DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
175 const SourceDataType*,
176 UTF8**,
177 UTF8*,
178 ConversionFlags),
179 DataExtractor& data,
180 Stream& stream,
181 char prefix_token = '@',
182 char quote = '"',
Enrico Granatad83bfce2013-04-02 21:25:34 +0000183 uint32_t sourceSize = 0)
Enrico Granataf68df122013-01-10 22:08:35 +0000184{
Enrico Granata93d59662013-01-14 23:53:26 +0000185 if (prefix_token != 0)
186 stream.Printf("%c",prefix_token);
187 if (quote != 0)
188 stream.Printf("%c",quote);
189 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf68df122013-01-10 22:08:35 +0000190 {
Enrico Granata93d59662013-01-14 23:53:26 +0000191 const int bufferSPSize = data.GetByteSize();
192 if (sourceSize == 0)
193 {
194 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Claytonaa4c47a2013-02-08 21:59:34 +0000195 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granata93d59662013-01-14 23:53:26 +0000196 }
197
198 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000199 SourceDataType *data_end_ptr = data_ptr + sourceSize;
200
201 while (data_ptr < data_end_ptr)
202 {
203 if (!*data_ptr)
204 {
205 data_end_ptr = data_ptr;
206 break;
207 }
208 data_ptr++;
209 }
210
Enrico Granata93d59662013-01-14 23:53:26 +0000211 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000212
Enrico Granata38352042013-01-11 02:44:00 +0000213 lldb::DataBufferSP utf8_data_buffer_sp;
214 UTF8* utf8_data_ptr = nullptr;
215 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granata93d59662013-01-14 23:53:26 +0000216
Enrico Granataf68df122013-01-10 22:08:35 +0000217 if (ConvertFunction)
Enrico Granata38352042013-01-11 02:44:00 +0000218 {
Enrico Granata56768392013-04-23 20:05:05 +0000219 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
Enrico Granata38352042013-01-11 02:44:00 +0000220 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
Enrico Granata56768392013-04-23 20:05:05 +0000221 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
Enrico Granataf68df122013-01-10 22:08:35 +0000222 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata38352042013-01-11 02:44:00 +0000223 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
224 }
Enrico Granataf68df122013-01-10 22:08:35 +0000225 else
226 {
227 // just copy the pointers - the cast is necessary to make the compiler happy
228 // but this should only happen if we are reading UTF8 data
229 utf8_data_ptr = (UTF8*)data_ptr;
230 utf8_data_end_ptr = (UTF8*)data_end_ptr;
231 }
232
Enrico Granata3309d882013-01-12 01:00:22 +0000233 // since we tend to accept partial data (and even partially malformed data)
234 // we might end up with no NULL terminator before the end_ptr
235 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf68df122013-01-10 22:08:35 +0000236 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
237 {
238 if (!*utf8_data_ptr)
239 break;
240 stream.Printf("%c",*utf8_data_ptr);
241 }
Enrico Granata93d59662013-01-14 23:53:26 +0000242 }
243 if (quote != 0)
244 stream.Printf("%c",quote);
245 return true;
246}
247
248template<typename SourceDataType>
Enrico Granata56768392013-04-23 20:05:05 +0000249class ReadUTFBufferAndDumpToStreamOptions
Enrico Granata93d59662013-01-14 23:53:26 +0000250{
Enrico Granata56768392013-04-23 20:05:05 +0000251public:
252 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
253 const SourceDataType*,
254 UTF8**,
255 UTF8*,
256 ConversionFlags);
257
258 ReadUTFBufferAndDumpToStreamOptions () :
259 m_conversion_function(NULL),
260 m_location(0),
261 m_process_sp(),
262 m_stream(NULL),
263 m_prefix_token('@'),
264 m_quote('"'),
265 m_source_size(0),
266 m_needs_zero_termination(true)
267 {
268 }
269
270 ReadUTFBufferAndDumpToStreamOptions&
271 SetConversionFunction (ConvertFunctionType f)
272 {
273 m_conversion_function = f;
274 return *this;
275 }
276
277 ConvertFunctionType
278 GetConversionFunction () const
279 {
280 return m_conversion_function;
281 }
282
283 ReadUTFBufferAndDumpToStreamOptions&
284 SetLocation (uint64_t l)
285 {
286 m_location = l;
287 return *this;
288 }
289
290 uint64_t
291 GetLocation () const
292 {
293 return m_location;
294 }
295
296 ReadUTFBufferAndDumpToStreamOptions&
297 SetProcessSP (ProcessSP p)
298 {
299 m_process_sp = p;
300 return *this;
301 }
302
303 ProcessSP
304 GetProcessSP () const
305 {
306 return m_process_sp;
307 }
308
309 ReadUTFBufferAndDumpToStreamOptions&
310 SetStream (Stream* s)
311 {
312 m_stream = s;
313 return *this;
314 }
315
316 Stream*
317 GetStream () const
318 {
319 return m_stream;
320 }
321
322 ReadUTFBufferAndDumpToStreamOptions&
323 SetPrefixToken (char p)
324 {
325 m_prefix_token = p;
326 return *this;
327 }
328
329 char
330 GetPrefixToken () const
331 {
332 return m_prefix_token;
333 }
334
335 ReadUTFBufferAndDumpToStreamOptions&
336 SetQuote (char q)
337 {
338 m_quote = q;
339 return *this;
340 }
341
342 char
343 GetQuote () const
344 {
345 return m_quote;
346 }
347
348 ReadUTFBufferAndDumpToStreamOptions&
349 SetSourceSize (uint32_t s)
350 {
351 m_source_size = s;
352 return *this;
353 }
354
355 uint32_t
356 GetSourceSize () const
357 {
358 return m_source_size;
359 }
360
361 ReadUTFBufferAndDumpToStreamOptions&
362 SetNeedsZeroTermination (bool z)
363 {
364 m_needs_zero_termination = z;
365 return *this;
366 }
367
368 bool
369 GetNeedsZeroTermination () const
370 {
371 return m_needs_zero_termination;
372 }
373
374private:
375 ConvertFunctionType m_conversion_function;
376 uint64_t m_location;
377 ProcessSP m_process_sp;
378 Stream* m_stream;
379 char m_prefix_token;
380 char m_quote;
381 uint32_t m_source_size;
382 bool m_needs_zero_termination;
383};
384
385template<typename SourceDataType>
386static bool
387ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
388{
389 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
Enrico Granata93d59662013-01-14 23:53:26 +0000390 return false;
Enrico Granata56768392013-04-23 20:05:05 +0000391
392 ProcessSP process_sp(options.GetProcessSP());
393
Enrico Granata93d59662013-01-14 23:53:26 +0000394 if (!process_sp)
395 return false;
396
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000397 const int type_width = sizeof(SourceDataType);
398 const int origin_encoding = 8 * type_width ;
Enrico Granata93d59662013-01-14 23:53:26 +0000399 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
400 return false;
401 // if not UTF8, I need a conversion function to return proper UTF8
Enrico Granata56768392013-04-23 20:05:05 +0000402 if (origin_encoding != 8 && !options.GetConversionFunction())
403 return false;
404
405 if (!options.GetStream())
Enrico Granata93d59662013-01-14 23:53:26 +0000406 return false;
407
Enrico Granata56768392013-04-23 20:05:05 +0000408 uint32_t sourceSize = options.GetSourceSize();
409 bool needs_zero_terminator = options.GetNeedsZeroTermination();
410
Enrico Granata23ab35a2013-04-02 23:07:55 +0000411 if (!sourceSize)
Enrico Granata56768392013-04-23 20:05:05 +0000412 {
Enrico Granata23ab35a2013-04-02 23:07:55 +0000413 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
Enrico Granata56768392013-04-23 20:05:05 +0000414 needs_zero_terminator = true;
415 }
Enrico Granata23ab35a2013-04-02 23:07:55 +0000416 else
417 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
418
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000419 const int bufferSPSize = sourceSize * type_width;
Enrico Granata93d59662013-01-14 23:53:26 +0000420
Enrico Granata93d59662013-01-14 23:53:26 +0000421 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
422
423 if (!buffer_sp->GetBytes())
424 return false;
425
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000426 Error error;
427 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
428
Enrico Granata56768392013-04-23 20:05:05 +0000429 size_t data_read = 0;
430 if (needs_zero_terminator)
431 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
432 else
433 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
434
Enrico Granata93d59662013-01-14 23:53:26 +0000435 if (error.Fail() || data_read == 0)
436 {
Enrico Granata56768392013-04-23 20:05:05 +0000437 options.GetStream()->Printf("unable to read data");
Enrico Granataf68df122013-01-10 22:08:35 +0000438 return true;
439 }
Enrico Granata93d59662013-01-14 23:53:26 +0000440
441 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
442
Enrico Granata56768392013-04-23 20:05:05 +0000443 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
Enrico Granataf68df122013-01-10 22:08:35 +0000444}
445
446bool
447lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
448{
449 ProcessSP process_sp = valobj.GetProcessSP();
450 if (!process_sp)
451 return false;
452
453 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
454
455 if (!valobj_addr)
456 return false;
457
Enrico Granata56768392013-04-23 20:05:05 +0000458 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
459 options.SetLocation(valobj_addr);
460 options.SetConversionFunction(ConvertUTF16toUTF8);
461 options.SetProcessSP(process_sp);
462 options.SetStream(&stream);
463 options.SetPrefixToken('u');
464
465 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000466 {
467 stream.Printf("Summary Unavailable");
468 return true;
469 }
470
471 return true;
472}
473
474bool
475lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
476{
477 ProcessSP process_sp = valobj.GetProcessSP();
478 if (!process_sp)
479 return false;
480
481 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
482
483 if (!valobj_addr)
484 return false;
485
Enrico Granata56768392013-04-23 20:05:05 +0000486 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
487 options.SetLocation(valobj_addr);
488 options.SetConversionFunction(ConvertUTF32toUTF8);
489 options.SetProcessSP(process_sp);
490 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000491 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000492
493 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000494 {
495 stream.Printf("Summary Unavailable");
496 return true;
497 }
498
499 return true;
500}
501
502bool
503lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
504{
Enrico Granata38352042013-01-11 02:44:00 +0000505 ProcessSP process_sp = valobj.GetProcessSP();
506 if (!process_sp)
507 return false;
508
Enrico Granata3309d882013-01-12 01:00:22 +0000509 lldb::addr_t data_addr = 0;
510
511 if (valobj.IsPointerType())
512 data_addr = valobj.GetValueAsUnsigned(0);
513 else if (valobj.IsArrayType())
514 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000515
Enrico Granata3309d882013-01-12 01:00:22 +0000516 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000517 return false;
518
519 clang::ASTContext* ast = valobj.GetClangAST();
520
521 if (!ast)
522 return false;
523
524 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
525
526 switch (wchar_size)
527 {
528 case 8:
Enrico Granata56768392013-04-23 20:05:05 +0000529 {
Enrico Granata38352042013-01-11 02:44:00 +0000530 // utf 8
Enrico Granata56768392013-04-23 20:05:05 +0000531
532 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
533 options.SetLocation(data_addr);
534 options.SetConversionFunction(nullptr);
535 options.SetProcessSP(process_sp);
536 options.SetStream(&stream);
537 options.SetPrefixToken('L');
538
539 return ReadUTFBufferAndDumpToStream(options);
540 }
Enrico Granata38352042013-01-11 02:44:00 +0000541 case 16:
Enrico Granata56768392013-04-23 20:05:05 +0000542 {
Enrico Granata38352042013-01-11 02:44:00 +0000543 // utf 16
Enrico Granata56768392013-04-23 20:05:05 +0000544 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
545 options.SetLocation(data_addr);
546 options.SetConversionFunction(ConvertUTF16toUTF8);
547 options.SetProcessSP(process_sp);
548 options.SetStream(&stream);
549 options.SetPrefixToken('L');
550
551 return ReadUTFBufferAndDumpToStream(options);
552 }
Enrico Granata38352042013-01-11 02:44:00 +0000553 case 32:
Enrico Granata56768392013-04-23 20:05:05 +0000554 {
Enrico Granata38352042013-01-11 02:44:00 +0000555 // utf 32
Enrico Granata56768392013-04-23 20:05:05 +0000556 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
557 options.SetLocation(data_addr);
558 options.SetConversionFunction(ConvertUTF32toUTF8);
559 options.SetProcessSP(process_sp);
560 options.SetStream(&stream);
561 options.SetPrefixToken('L');
562
563 return ReadUTFBufferAndDumpToStream(options);
564 }
Enrico Granata93d59662013-01-14 23:53:26 +0000565 default:
566 stream.Printf("size for wchar_t is not valid");
567 return true;
568 }
569 return true;
570}
571
572bool
573lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
574{
575 DataExtractor data;
576 valobj.GetData(data);
577
578 std::string value;
579 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
580 if (!value.empty())
581 stream.Printf("%s ", value.c_str());
582
583 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
584}
585
586bool
587lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
588{
589 DataExtractor data;
590 valobj.GetData(data);
591
592 std::string value;
593 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
594 if (!value.empty())
595 stream.Printf("%s ", value.c_str());
596
597 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
598}
599
600bool
601lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
602{
603 DataExtractor data;
604 valobj.GetData(data);
605
606 clang::ASTContext* ast = valobj.GetClangAST();
607
608 if (!ast)
609 return false;
610
611 std::string value;
612
613 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
614
615 switch (wchar_size)
616 {
617 case 8:
618 // utf 8
619 valobj.GetValueAsCString(lldb::eFormatChar, value);
620 if (!value.empty())
621 stream.Printf("%s ", value.c_str());
622 return DumpUTFBufferToStream<UTF8>(nullptr,
623 data,
624 stream,
625 'L',
626 '\'',
627 1);
628 case 16:
629 // utf 16
630 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
631 if (!value.empty())
632 stream.Printf("%s ", value.c_str());
633 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
634 data,
635 stream,
636 'L',
637 '\'',
638 1);
639 case 32:
640 // utf 32
641 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
642 if (!value.empty())
643 stream.Printf("%s ", value.c_str());
644 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
645 data,
646 stream,
647 'L',
648 '\'',
649 1);
Enrico Granata38352042013-01-11 02:44:00 +0000650 default:
651 stream.Printf("size for wchar_t is not valid");
652 return true;
653 }
654 return true;
Enrico Granataf68df122013-01-10 22:08:35 +0000655}
656
Enrico Granata3309d882013-01-12 01:00:22 +0000657// this function extracts information from a libcxx std::basic_string<>
658// irregardless of template arguments. it reports the size (in item count not bytes)
659// and the location in memory where the string data can be found
660static bool
661ExtractLibcxxStringInfo (ValueObject& valobj,
662 ValueObjectSP &location_sp,
663 uint64_t& size)
664{
665 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
666 if (!D)
667 return false;
668
669 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
670 if (!size_mode)
671 return false;
672
673 uint64_t size_mode_value(size_mode->GetValueAsUnsigned(0));
674
675 if ((size_mode_value & 1) == 0) // this means the string is in short-mode and the data is stored inline
676 {
677 ValueObjectSP s(D->GetChildAtIndex(1, true));
678 if (!s)
679 return false;
680 size = ((size_mode_value >> 1) % 256);
681 location_sp = s->GetChildAtIndex(1, true);
682 return (location_sp.get() != nullptr);
683 }
684 else
685 {
686 ValueObjectSP l(D->GetChildAtIndex(0, true));
687 if (!l)
688 return false;
689 location_sp = l->GetChildAtIndex(2, true);
690 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
691 if (!size_vo || !location_sp)
692 return false;
693 size = size_vo->GetValueAsUnsigned(0);
694 return true;
695 }
696}
697
698bool
699lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
700{
701 uint64_t size = 0;
702 ValueObjectSP location_sp((ValueObject*)nullptr);
703 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
704 return false;
705 if (size == 0)
706 {
707 stream.Printf("L\"\"");
708 return true;
709 }
710 if (!location_sp)
711 return false;
712 return WCharStringSummaryProvider(*location_sp.get(), stream);
713}
714
715bool
716lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
717{
718 uint64_t size = 0;
719 ValueObjectSP location_sp((ValueObject*)nullptr);
720 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
721 return false;
722 if (size == 0)
723 {
724 stream.Printf("\"\"");
725 return true;
726 }
727 if (!location_sp)
728 return false;
729 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000730 if (location_sp->ReadPointedString(stream,
731 error,
732 0, // max length is decided by the settings
733 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
734 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000735 return error.Success();
736}
737
Enrico Granata55900862013-03-15 18:55:30 +0000738bool
739lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
740{
741 ProcessSP process_sp = valobj.GetProcessSP();
742 if (!process_sp)
743 return false;
744
745 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
746
747 if (!runtime)
748 return false;
749
Greg Clayton03da4cc2013-04-19 21:31:16 +0000750 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000751
752 if (!descriptor.get() || !descriptor->IsValid())
753 return false;
754
755 const char* class_name = descriptor->GetClassName().GetCString();
756
757 if (!class_name || !*class_name)
758 return false;
759
760 stream.Printf("%s",class_name);
761 return true;
762}
763
Enrico Granatac76b97b2013-04-26 00:59:02 +0000764class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
765{
766public:
767 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
768 SyntheticChildrenFrontEnd(*valobj_sp.get())
769 {
770 }
771
772 virtual size_t
773 CalculateNumChildren ()
774 {
775 return 0;
776 }
777
778 virtual lldb::ValueObjectSP
779 GetChildAtIndex (size_t idx)
780 {
781 return lldb::ValueObjectSP();
782 }
783
784 virtual bool
785 Update()
786 {
787 return false;
788 }
789
790 virtual bool
791 MightHaveChildren ()
792 {
793 return false;
794 }
795
796 virtual size_t
797 GetIndexOfChildWithName (const ConstString &name)
798 {
799 return UINT32_MAX;
800 }
801
802 virtual
803 ~ObjCClassSyntheticChildrenFrontEnd ()
804 {
805 }
806};
807
808SyntheticChildrenFrontEnd*
809lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
810{
811 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
812}
813
Enrico Granataf5196282012-09-04 18:48:21 +0000814template<bool needs_at>
815bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000816lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000817{
818 ProcessSP process_sp = valobj.GetProcessSP();
819 if (!process_sp)
820 return false;
821
822 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
823
824 if (!runtime)
825 return false;
826
827 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
828
829 if (!descriptor.get() || !descriptor->IsValid())
830 return false;
831
832 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
833 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
834
835 if (!valobj_addr)
836 return false;
837
838 uint64_t value = 0;
839
840 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000841
842 if (!class_name || !*class_name)
843 return false;
844
Enrico Granataf5196282012-09-04 18:48:21 +0000845 if (!strcmp(class_name,"NSConcreteData") ||
846 !strcmp(class_name,"NSConcreteMutableData") ||
847 !strcmp(class_name,"__NSCFData"))
848 {
849 uint32_t offset = (is_64bit ? 16 : 8);
850 Error error;
851 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
852 if (error.Fail())
853 return false;
854 }
855 else
856 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000857 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000858 return false;
859 }
860
Daniel Malead01b2952012-11-29 21:49:15 +0000861 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000862 (needs_at ? "@\"" : ""),
863 value,
864 (value > 1 ? "s" : ""),
865 (needs_at ? "\"" : ""));
866
867 return true;
868}
869
Enrico Granata87f00b42013-02-21 20:31:18 +0000870static bool
871ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
872 lldb::ProcessSP& process_sp,
873 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000874 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000875 Error* error = NULL,
876 size_t *data_read = NULL,
877 char prefix_token = '@',
878 char quote = '"')
879{
880 Error my_error;
881 size_t my_data_read;
882 if (!process_sp || location == 0)
883 return false;
884
Enrico Granata23ab35a2013-04-02 23:07:55 +0000885 if (!size)
886 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
887 else
888 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000889
890 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
891
892 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
893
894 if (error)
895 *error = my_error;
896 if (data_read)
897 *data_read = my_data_read;
898
899 if (my_error.Fail())
900 return false;
901 if (my_data_read)
902 dest.Printf("%c%c%s%c",prefix_token,quote,(char*)buffer_sp->GetBytes(),quote);
903
904 return true;
905}
906
Enrico Granatad83bfce2013-04-02 21:25:34 +0000907#ifdef WANT_DEEP_PRINT
908struct lldb__notInlineMutable {
909 void *buffer;
910 signed long length;
911 signed long capacity;
912 unsigned int hasGap:1;
913 unsigned int isFixedCapacity:1;
914 unsigned int isExternalMutable:1;
915 unsigned int capacityProvidedExternally:1;
916#if __LP64__
917 unsigned long desiredCapacity:60;
918#else
919 unsigned long desiredCapacity:28;
920#endif
921 void* contentsAllocator;
922};
923
924struct lldb__CFString {
925 uintptr_t _cfisa;
926 uint8_t _cfinfo[4];
927 uint32_t _rc;
928 union {
929 struct __inline1 {
930 signed long length;
931 } inline1;
932 struct __notInlineImmutable1 {
933 void *buffer;
934 signed long length;
935 void* contentsDeallocator;
936 } notInlineImmutable1;
937 struct __notInlineImmutable2 {
938 void *buffer;
939 void* contentsDeallocator;
940 } notInlineImmutable2;
941 struct lldb__notInlineMutable notInlineMutable;
942 } variants;
943};
944#endif
945
Enrico Granataf5196282012-09-04 18:48:21 +0000946bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000947lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000948{
949 ProcessSP process_sp = valobj.GetProcessSP();
950 if (!process_sp)
951 return false;
952
953 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
954
955 if (!runtime)
956 return false;
957
958 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
959
960 if (!descriptor.get() || !descriptor->IsValid())
961 return false;
962
963 uint32_t ptr_size = process_sp->GetAddressByteSize();
964
965 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
966
967 if (!valobj_addr)
968 return false;
969
970 const char* class_name = descriptor->GetClassName().GetCString();
971
Enrico Granata60b81df2012-09-29 00:45:53 +0000972 if (!class_name || !*class_name)
973 return false;
974
Enrico Granataf5196282012-09-04 18:48:21 +0000975 uint64_t info_bits_location = valobj_addr + ptr_size;
976 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
977 info_bits_location += 3;
978
Enrico Granata87f00b42013-02-21 20:31:18 +0000979 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000980
981 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
982 if (error.Fail())
983 return false;
984
985 bool is_mutable = (info_bits & 1) == 1;
986 bool is_inline = (info_bits & 0x60) == 0;
987 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
988 bool is_unicode = (info_bits & 0x10) == 0x10;
989 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000990 bool has_null = (info_bits & 8) == 8;
991
992 size_t explicit_length = 0;
993 if (!has_null && has_explicit_length && !is_special)
994 {
995 lldb::addr_t explicit_length_offset = 2*ptr_size;
996 if (is_mutable and not is_inline)
997 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
998 else if (is_inline)
999 explicit_length = explicit_length + 0; // inline1.length;
1000 else if (not is_inline and not is_mutable)
1001 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1002 else
1003 explicit_length_offset = 0;
1004
1005 if (explicit_length_offset)
1006 {
1007 explicit_length_offset = valobj_addr + explicit_length_offset;
1008 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1009 }
1010 }
1011
1012#ifdef WANT_DEEP_PRINT
1013 lldb__CFString my_string_data;
1014 process_sp->ReadMemory(valobj_addr, &my_string_data, sizeof(lldb__CFString),error);
1015
1016 printf(R"(
1017 __CFString my_string_data = {
1018 uintptr_t _cfisa = %lu
1019 uint8_t _cfinfo[4] = %c%c%c%c
1020 uint32_t _rc = %d
1021 union {
1022 struct __inline1 {
1023 signed long length = %ld
1024 } inline1;
1025 struct __notInlineImmutable1 {
1026 void *buffer = %p
1027 signed long length = %ld
1028 void* contentsDeallocator = %p
1029 } notInlineImmutable1;
1030 struct __notInlineImmutable2 {
1031 void *buffer = %p
1032 void* contentsDeallocator = %p
1033 } notInlineImmutable2;
1034 struct __notInlineMutable notInlineMutable {
1035 void *buffer = %p
1036 signed long length = %ld
1037 signed long capacity = %ld
1038 unsigned int hasGap:1 = %d
1039 unsigned int isFixedCapacity:1 = %d
1040 unsigned int isExternalMutable:1 = %d
1041 unsigned int capacityProvidedExternally:1 = %d
1042#if __LP64__
1043 unsigned long desiredCapacity:60 = %lu
1044#else
1045 unsigned long desiredCapacity:28 = %lu
1046#endif
1047 void* contentsAllocator = %p
1048 }
Enrico Granata56768392013-04-23 20:05:05 +00001049 } variants; ==> (M:%dI:%dL:%zuU:%dS:%dN:%d)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001050 };\n)",
1051 my_string_data._cfisa,
1052 my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
1053 my_string_data._rc,
1054 my_string_data.variants.inline1.length,
1055 my_string_data.variants.notInlineImmutable1.buffer,
1056 my_string_data.variants.notInlineImmutable1.length,
1057 my_string_data.variants.notInlineImmutable1.contentsDeallocator,
1058 my_string_data.variants.notInlineImmutable2.buffer,
1059 my_string_data.variants.notInlineImmutable2.contentsDeallocator,
1060 my_string_data.variants.notInlineMutable.buffer,
1061 my_string_data.variants.notInlineMutable.length,
1062 my_string_data.variants.notInlineMutable.capacity,
1063 my_string_data.variants.notInlineMutable.hasGap,
1064 my_string_data.variants.notInlineMutable.isFixedCapacity,
1065 my_string_data.variants.notInlineMutable.isExternalMutable,
1066 my_string_data.variants.notInlineMutable.capacityProvidedExternally,
1067 my_string_data.variants.notInlineMutable.desiredCapacity,
1068 my_string_data.variants.notInlineMutable.desiredCapacity,
Enrico Granata56768392013-04-23 20:05:05 +00001069 my_string_data.variants.notInlineMutable.contentsAllocator,
1070 is_mutable,
1071 is_inline,
1072 explicit_length,
1073 is_unicode,
1074 is_special,
1075 has_null);
Enrico Granatad83bfce2013-04-02 21:25:34 +00001076#endif
Enrico Granataf5196282012-09-04 18:48:21 +00001077
1078 if (strcmp(class_name,"NSString") &&
1079 strcmp(class_name,"CFStringRef") &&
1080 strcmp(class_name,"CFMutableStringRef") &&
1081 strcmp(class_name,"__NSCFConstantString") &&
1082 strcmp(class_name,"__NSCFString") &&
1083 strcmp(class_name,"NSCFConstantString") &&
1084 strcmp(class_name,"NSCFString") &&
1085 strcmp(class_name,"NSPathStore2"))
1086 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001087 // not one of us - but tell me class name
1088 stream.Printf("class name = %s",class_name);
1089 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001090 }
1091
1092 if (is_mutable)
1093 {
1094 uint64_t location = 2 * ptr_size + valobj_addr;
1095 location = process_sp->ReadPointerFromMemory(location, error);
1096 if (error.Fail())
1097 return false;
1098 if (has_explicit_length and is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001099 {
1100 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1101 options.SetConversionFunction(ConvertUTF16toUTF8);
1102 options.SetLocation(location);
1103 options.SetProcessSP(process_sp);
1104 options.SetStream(&stream);
1105 options.SetPrefixToken('@');
1106 options.SetQuote('"');
1107 options.SetSourceSize(explicit_length);
1108 options.SetNeedsZeroTermination(false);
1109 return ReadUTFBufferAndDumpToStream (options);
1110 }
Enrico Granataf5196282012-09-04 18:48:21 +00001111 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001112 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001113 }
1114 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1115 {
1116 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001117 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001118 }
1119 else if (is_unicode)
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 (is_inline)
1123 {
1124 if (!has_explicit_length)
1125 {
1126 stream.Printf("found new combo");
1127 return true;
1128 }
1129 else
1130 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001131 }
Enrico Granataf5196282012-09-04 18:48:21 +00001132 else
1133 {
1134 location = process_sp->ReadPointerFromMemory(location, error);
1135 if (error.Fail())
1136 return false;
1137 }
Enrico Granata56768392013-04-23 20:05:05 +00001138 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1139 options.SetConversionFunction(ConvertUTF16toUTF8);
1140 options.SetLocation(location);
1141 options.SetProcessSP(process_sp);
1142 options.SetStream(&stream);
1143 options.SetPrefixToken('@');
1144 options.SetQuote('"');
1145 options.SetSourceSize(explicit_length);
1146 options.SetNeedsZeroTermination(has_explicit_length == false);
1147 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001148 }
1149 else if (is_special)
1150 {
1151 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001152 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1153 options.SetConversionFunction(ConvertUTF16toUTF8);
1154 options.SetLocation(location);
1155 options.SetProcessSP(process_sp);
1156 options.SetStream(&stream);
1157 options.SetPrefixToken('@');
1158 options.SetQuote('"');
1159 options.SetSourceSize(explicit_length);
1160 options.SetNeedsZeroTermination(has_explicit_length == false);
1161 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001162 }
1163 else if (is_inline)
1164 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001165 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001166 if (!has_explicit_length)
1167 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001168 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001169 }
1170 else
1171 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001172 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001173 location = process_sp->ReadPointerFromMemory(location, error);
1174 if (error.Fail())
1175 return false;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001176 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001177 }
1178
1179 stream.Printf("class name = %s",class_name);
1180 return true;
1181
1182}
1183
Enrico Granataf175ad12012-10-03 23:53:45 +00001184bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001185lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1186{
1187 TargetSP target_sp(valobj.GetTargetSP());
1188 if (!target_sp)
1189 return false;
1190 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1191 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1192 if (!pointee)
1193 return false;
1194 pointee += addr_size;
1195 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1196 ExecutionContext exe_ctx(target_sp,false);
1197 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1198 if (!child_ptr_sp)
1199 return false;
1200 DataExtractor data;
1201 child_ptr_sp->GetData(data);
1202 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1203 child_sp->GetValueAsUnsigned(0);
1204 if (child_sp)
1205 return NSStringSummaryProvider(*child_sp, stream);
1206 return false;
1207}
1208
1209bool
1210lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1211{
1212 return NSAttributedStringSummaryProvider(valobj, stream);
1213}
1214
1215bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001216lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1217{
1218 stream.Printf("%s",valobj.GetObjectDescription());
1219 return true;
1220}
1221
Enrico Granatab5887262012-10-29 21:18:03 +00001222bool
1223lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1224{
1225 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1226 valobj.GetClangAST(),
1227 NULL);
1228
1229 ValueObjectSP real_guy_sp = valobj.GetSP();
1230
1231 if (type_info & ClangASTContext::eTypeIsPointer)
1232 {
1233 Error err;
1234 real_guy_sp = valobj.Dereference(err);
1235 if (err.Fail() || !real_guy_sp)
1236 return false;
1237 }
1238 else if (type_info & ClangASTContext::eTypeIsReference)
1239 {
1240 real_guy_sp = valobj.GetChildAtIndex(0, true);
1241 if (!real_guy_sp)
1242 return false;
1243 }
1244 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1245 if (value == 0)
1246 {
1247 stream.Printf("NO");
1248 return true;
1249 }
1250 stream.Printf("YES");
1251 return true;
1252}
1253
1254template <bool is_sel_ptr>
1255bool
1256lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1257{
Enrico Granata75dfb432013-02-15 00:06:04 +00001258 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001259
Enrico Granata75dfb432013-02-15 00:06:04 +00001260 if (!valobj.GetClangAST())
Enrico Granatab5887262012-10-29 21:18:03 +00001261 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001262 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1263 if (!char_opaque_type)
1264 return false;
1265 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1266
Enrico Granatab5887262012-10-29 21:18:03 +00001267 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1268
Enrico Granata75dfb432013-02-15 00:06:04 +00001269 if (is_sel_ptr)
1270 {
1271 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1272 if (data_address == LLDB_INVALID_ADDRESS)
1273 return false;
1274 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1275 }
1276 else
1277 {
1278 DataExtractor data;
1279 valobj.GetData(data);
1280 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1281 }
Enrico Granatab5887262012-10-29 21:18:03 +00001282
Enrico Granata75dfb432013-02-15 00:06:04 +00001283 if (!valobj_sp)
1284 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001285
1286 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1287 return true;
1288}
1289
Enrico Granata6d37cc62013-03-19 00:27:22 +00001290// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1291// this call gives the POSIX equivalent of the Cocoa epoch
1292time_t
Enrico Granata92373532013-03-19 22:58:48 +00001293lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001294{
1295 static time_t epoch = 0;
1296 if (!epoch)
1297 {
1298 tzset();
1299 tm tm_epoch;
1300 tm_epoch.tm_sec = 0;
1301 tm_epoch.tm_hour = 0;
1302 tm_epoch.tm_min = 0;
1303 tm_epoch.tm_mon = 0;
1304 tm_epoch.tm_mday = 1;
1305 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1306 tm_epoch.tm_isdst = -1;
1307 tm_epoch.tm_gmtoff = 0;
1308 tm_epoch.tm_zone = NULL;
1309 epoch = timegm(&tm_epoch);
1310 }
1311 return epoch;
1312}
1313
Greg Claytonc7bece562013-01-25 18:06:21 +00001314size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001315lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001316{
1317 if (!item_name || !*item_name)
1318 return UINT32_MAX;
1319 if (*item_name != '[')
1320 return UINT32_MAX;
1321 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001322 char* endptr = NULL;
1323 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1324 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001325 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001326 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001327 return UINT32_MAX;
1328 return idx;
1329}
1330
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001331lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1332 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001333SyntheticChildrenFrontEnd(*valobj_sp.get()),
1334m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001335m_item_name(item_name),
1336m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001337{
1338 if (valobj_sp)
1339 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001340}
1341
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001342bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001343lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001344{
Enrico Granata6eca3552013-03-28 18:50:54 +00001345 m_item_sp.reset();
1346
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001347 ValueObjectSP valobj_sp = m_backend.GetSP();
1348 if (!valobj_sp)
1349 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001350
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001351 if (!valobj_sp)
1352 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001353
1354 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1355 if (!item_ptr)
1356 return false;
1357 if (item_ptr->GetValueAsUnsigned(0) == 0)
1358 return false;
1359 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001360 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001361 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
1362 if (err.Fail())
1363 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001364 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001365}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001366
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001367size_t
1368lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1369{
1370 return 1;
1371}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001372
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001373lldb::ValueObjectSP
1374lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1375{
1376 if (idx == 0)
1377 return m_item_sp;
1378 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001379}
1380
1381bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001382lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001383{
1384 return true;
1385}
1386
1387size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001388lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001389{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001390 if (name == ConstString("item"))
1391 return 0;
1392 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001393}
1394
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001395lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001396{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001397}
1398
Enrico Granataf5196282012-09-04 18:48:21 +00001399template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001400lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1401
1402template bool
1403lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001404
1405template bool
1406lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1407
1408template bool
1409lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;