blob: 035760431c043f9eb2e84dc2f39a6b677c18912c [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);
491 options.SetPrefixToken('u');
492
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 Granataf5196282012-09-04 18:48:21 +0000764template<bool needs_at>
765bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000766lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000767{
768 ProcessSP process_sp = valobj.GetProcessSP();
769 if (!process_sp)
770 return false;
771
772 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
773
774 if (!runtime)
775 return false;
776
777 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
778
779 if (!descriptor.get() || !descriptor->IsValid())
780 return false;
781
782 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
783 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
784
785 if (!valobj_addr)
786 return false;
787
788 uint64_t value = 0;
789
790 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000791
792 if (!class_name || !*class_name)
793 return false;
794
Enrico Granataf5196282012-09-04 18:48:21 +0000795 if (!strcmp(class_name,"NSConcreteData") ||
796 !strcmp(class_name,"NSConcreteMutableData") ||
797 !strcmp(class_name,"__NSCFData"))
798 {
799 uint32_t offset = (is_64bit ? 16 : 8);
800 Error error;
801 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
802 if (error.Fail())
803 return false;
804 }
805 else
806 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000807 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000808 return false;
809 }
810
Daniel Malead01b2952012-11-29 21:49:15 +0000811 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000812 (needs_at ? "@\"" : ""),
813 value,
814 (value > 1 ? "s" : ""),
815 (needs_at ? "\"" : ""));
816
817 return true;
818}
819
Enrico Granata87f00b42013-02-21 20:31:18 +0000820static bool
821ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
822 lldb::ProcessSP& process_sp,
823 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000824 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000825 Error* error = NULL,
826 size_t *data_read = NULL,
827 char prefix_token = '@',
828 char quote = '"')
829{
830 Error my_error;
831 size_t my_data_read;
832 if (!process_sp || location == 0)
833 return false;
834
Enrico Granata23ab35a2013-04-02 23:07:55 +0000835 if (!size)
836 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
837 else
838 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000839
840 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
841
842 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
843
844 if (error)
845 *error = my_error;
846 if (data_read)
847 *data_read = my_data_read;
848
849 if (my_error.Fail())
850 return false;
851 if (my_data_read)
852 dest.Printf("%c%c%s%c",prefix_token,quote,(char*)buffer_sp->GetBytes(),quote);
853
854 return true;
855}
856
Enrico Granatad83bfce2013-04-02 21:25:34 +0000857#ifdef WANT_DEEP_PRINT
858struct lldb__notInlineMutable {
859 void *buffer;
860 signed long length;
861 signed long capacity;
862 unsigned int hasGap:1;
863 unsigned int isFixedCapacity:1;
864 unsigned int isExternalMutable:1;
865 unsigned int capacityProvidedExternally:1;
866#if __LP64__
867 unsigned long desiredCapacity:60;
868#else
869 unsigned long desiredCapacity:28;
870#endif
871 void* contentsAllocator;
872};
873
874struct lldb__CFString {
875 uintptr_t _cfisa;
876 uint8_t _cfinfo[4];
877 uint32_t _rc;
878 union {
879 struct __inline1 {
880 signed long length;
881 } inline1;
882 struct __notInlineImmutable1 {
883 void *buffer;
884 signed long length;
885 void* contentsDeallocator;
886 } notInlineImmutable1;
887 struct __notInlineImmutable2 {
888 void *buffer;
889 void* contentsDeallocator;
890 } notInlineImmutable2;
891 struct lldb__notInlineMutable notInlineMutable;
892 } variants;
893};
894#endif
895
Enrico Granataf5196282012-09-04 18:48:21 +0000896bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000897lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000898{
899 ProcessSP process_sp = valobj.GetProcessSP();
900 if (!process_sp)
901 return false;
902
903 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
904
905 if (!runtime)
906 return false;
907
908 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
909
910 if (!descriptor.get() || !descriptor->IsValid())
911 return false;
912
913 uint32_t ptr_size = process_sp->GetAddressByteSize();
914
915 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
916
917 if (!valobj_addr)
918 return false;
919
920 const char* class_name = descriptor->GetClassName().GetCString();
921
Enrico Granata60b81df2012-09-29 00:45:53 +0000922 if (!class_name || !*class_name)
923 return false;
924
Enrico Granataf5196282012-09-04 18:48:21 +0000925 uint64_t info_bits_location = valobj_addr + ptr_size;
926 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
927 info_bits_location += 3;
928
Enrico Granata87f00b42013-02-21 20:31:18 +0000929 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +0000930
931 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
932 if (error.Fail())
933 return false;
934
935 bool is_mutable = (info_bits & 1) == 1;
936 bool is_inline = (info_bits & 0x60) == 0;
937 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
938 bool is_unicode = (info_bits & 0x10) == 0x10;
939 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +0000940 bool has_null = (info_bits & 8) == 8;
941
942 size_t explicit_length = 0;
943 if (!has_null && has_explicit_length && !is_special)
944 {
945 lldb::addr_t explicit_length_offset = 2*ptr_size;
946 if (is_mutable and not is_inline)
947 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
948 else if (is_inline)
949 explicit_length = explicit_length + 0; // inline1.length;
950 else if (not is_inline and not is_mutable)
951 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
952 else
953 explicit_length_offset = 0;
954
955 if (explicit_length_offset)
956 {
957 explicit_length_offset = valobj_addr + explicit_length_offset;
958 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
959 }
960 }
961
962#ifdef WANT_DEEP_PRINT
963 lldb__CFString my_string_data;
964 process_sp->ReadMemory(valobj_addr, &my_string_data, sizeof(lldb__CFString),error);
965
966 printf(R"(
967 __CFString my_string_data = {
968 uintptr_t _cfisa = %lu
969 uint8_t _cfinfo[4] = %c%c%c%c
970 uint32_t _rc = %d
971 union {
972 struct __inline1 {
973 signed long length = %ld
974 } inline1;
975 struct __notInlineImmutable1 {
976 void *buffer = %p
977 signed long length = %ld
978 void* contentsDeallocator = %p
979 } notInlineImmutable1;
980 struct __notInlineImmutable2 {
981 void *buffer = %p
982 void* contentsDeallocator = %p
983 } notInlineImmutable2;
984 struct __notInlineMutable notInlineMutable {
985 void *buffer = %p
986 signed long length = %ld
987 signed long capacity = %ld
988 unsigned int hasGap:1 = %d
989 unsigned int isFixedCapacity:1 = %d
990 unsigned int isExternalMutable:1 = %d
991 unsigned int capacityProvidedExternally:1 = %d
992#if __LP64__
993 unsigned long desiredCapacity:60 = %lu
994#else
995 unsigned long desiredCapacity:28 = %lu
996#endif
997 void* contentsAllocator = %p
998 }
Enrico Granata56768392013-04-23 20:05:05 +0000999 } variants; ==> (M:%dI:%dL:%zuU:%dS:%dN:%d)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001000 };\n)",
1001 my_string_data._cfisa,
1002 my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
1003 my_string_data._rc,
1004 my_string_data.variants.inline1.length,
1005 my_string_data.variants.notInlineImmutable1.buffer,
1006 my_string_data.variants.notInlineImmutable1.length,
1007 my_string_data.variants.notInlineImmutable1.contentsDeallocator,
1008 my_string_data.variants.notInlineImmutable2.buffer,
1009 my_string_data.variants.notInlineImmutable2.contentsDeallocator,
1010 my_string_data.variants.notInlineMutable.buffer,
1011 my_string_data.variants.notInlineMutable.length,
1012 my_string_data.variants.notInlineMutable.capacity,
1013 my_string_data.variants.notInlineMutable.hasGap,
1014 my_string_data.variants.notInlineMutable.isFixedCapacity,
1015 my_string_data.variants.notInlineMutable.isExternalMutable,
1016 my_string_data.variants.notInlineMutable.capacityProvidedExternally,
1017 my_string_data.variants.notInlineMutable.desiredCapacity,
1018 my_string_data.variants.notInlineMutable.desiredCapacity,
Enrico Granata56768392013-04-23 20:05:05 +00001019 my_string_data.variants.notInlineMutable.contentsAllocator,
1020 is_mutable,
1021 is_inline,
1022 explicit_length,
1023 is_unicode,
1024 is_special,
1025 has_null);
Enrico Granatad83bfce2013-04-02 21:25:34 +00001026#endif
Enrico Granataf5196282012-09-04 18:48:21 +00001027
1028 if (strcmp(class_name,"NSString") &&
1029 strcmp(class_name,"CFStringRef") &&
1030 strcmp(class_name,"CFMutableStringRef") &&
1031 strcmp(class_name,"__NSCFConstantString") &&
1032 strcmp(class_name,"__NSCFString") &&
1033 strcmp(class_name,"NSCFConstantString") &&
1034 strcmp(class_name,"NSCFString") &&
1035 strcmp(class_name,"NSPathStore2"))
1036 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001037 // not one of us - but tell me class name
1038 stream.Printf("class name = %s",class_name);
1039 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001040 }
1041
1042 if (is_mutable)
1043 {
1044 uint64_t location = 2 * ptr_size + valobj_addr;
1045 location = process_sp->ReadPointerFromMemory(location, error);
1046 if (error.Fail())
1047 return false;
1048 if (has_explicit_length and is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001049 {
1050 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1051 options.SetConversionFunction(ConvertUTF16toUTF8);
1052 options.SetLocation(location);
1053 options.SetProcessSP(process_sp);
1054 options.SetStream(&stream);
1055 options.SetPrefixToken('@');
1056 options.SetQuote('"');
1057 options.SetSourceSize(explicit_length);
1058 options.SetNeedsZeroTermination(false);
1059 return ReadUTFBufferAndDumpToStream (options);
1060 }
Enrico Granataf5196282012-09-04 18:48:21 +00001061 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001062 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001063 }
1064 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1065 {
1066 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001067 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001068 }
1069 else if (is_unicode)
1070 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001071 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001072 if (is_inline)
1073 {
1074 if (!has_explicit_length)
1075 {
1076 stream.Printf("found new combo");
1077 return true;
1078 }
1079 else
1080 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001081 }
Enrico Granataf5196282012-09-04 18:48:21 +00001082 else
1083 {
1084 location = process_sp->ReadPointerFromMemory(location, error);
1085 if (error.Fail())
1086 return false;
1087 }
Enrico Granata56768392013-04-23 20:05:05 +00001088 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1089 options.SetConversionFunction(ConvertUTF16toUTF8);
1090 options.SetLocation(location);
1091 options.SetProcessSP(process_sp);
1092 options.SetStream(&stream);
1093 options.SetPrefixToken('@');
1094 options.SetQuote('"');
1095 options.SetSourceSize(explicit_length);
1096 options.SetNeedsZeroTermination(has_explicit_length == false);
1097 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001098 }
1099 else if (is_special)
1100 {
1101 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001102 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1103 options.SetConversionFunction(ConvertUTF16toUTF8);
1104 options.SetLocation(location);
1105 options.SetProcessSP(process_sp);
1106 options.SetStream(&stream);
1107 options.SetPrefixToken('@');
1108 options.SetQuote('"');
1109 options.SetSourceSize(explicit_length);
1110 options.SetNeedsZeroTermination(has_explicit_length == false);
1111 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001112 }
1113 else if (is_inline)
1114 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001115 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001116 if (!has_explicit_length)
1117 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001118 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001119 }
1120 else
1121 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001122 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001123 location = process_sp->ReadPointerFromMemory(location, error);
1124 if (error.Fail())
1125 return false;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001126 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001127 }
1128
1129 stream.Printf("class name = %s",class_name);
1130 return true;
1131
1132}
1133
Enrico Granataf175ad12012-10-03 23:53:45 +00001134bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001135lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1136{
1137 TargetSP target_sp(valobj.GetTargetSP());
1138 if (!target_sp)
1139 return false;
1140 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1141 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1142 if (!pointee)
1143 return false;
1144 pointee += addr_size;
1145 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1146 ExecutionContext exe_ctx(target_sp,false);
1147 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1148 if (!child_ptr_sp)
1149 return false;
1150 DataExtractor data;
1151 child_ptr_sp->GetData(data);
1152 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1153 child_sp->GetValueAsUnsigned(0);
1154 if (child_sp)
1155 return NSStringSummaryProvider(*child_sp, stream);
1156 return false;
1157}
1158
1159bool
1160lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1161{
1162 return NSAttributedStringSummaryProvider(valobj, stream);
1163}
1164
1165bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001166lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1167{
1168 stream.Printf("%s",valobj.GetObjectDescription());
1169 return true;
1170}
1171
Enrico Granatab5887262012-10-29 21:18:03 +00001172bool
1173lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1174{
1175 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1176 valobj.GetClangAST(),
1177 NULL);
1178
1179 ValueObjectSP real_guy_sp = valobj.GetSP();
1180
1181 if (type_info & ClangASTContext::eTypeIsPointer)
1182 {
1183 Error err;
1184 real_guy_sp = valobj.Dereference(err);
1185 if (err.Fail() || !real_guy_sp)
1186 return false;
1187 }
1188 else if (type_info & ClangASTContext::eTypeIsReference)
1189 {
1190 real_guy_sp = valobj.GetChildAtIndex(0, true);
1191 if (!real_guy_sp)
1192 return false;
1193 }
1194 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1195 if (value == 0)
1196 {
1197 stream.Printf("NO");
1198 return true;
1199 }
1200 stream.Printf("YES");
1201 return true;
1202}
1203
1204template <bool is_sel_ptr>
1205bool
1206lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1207{
Enrico Granata75dfb432013-02-15 00:06:04 +00001208 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001209
Enrico Granata75dfb432013-02-15 00:06:04 +00001210 if (!valobj.GetClangAST())
Enrico Granatab5887262012-10-29 21:18:03 +00001211 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001212 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1213 if (!char_opaque_type)
1214 return false;
1215 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1216
Enrico Granatab5887262012-10-29 21:18:03 +00001217 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1218
Enrico Granata75dfb432013-02-15 00:06:04 +00001219 if (is_sel_ptr)
1220 {
1221 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1222 if (data_address == LLDB_INVALID_ADDRESS)
1223 return false;
1224 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1225 }
1226 else
1227 {
1228 DataExtractor data;
1229 valobj.GetData(data);
1230 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1231 }
Enrico Granatab5887262012-10-29 21:18:03 +00001232
Enrico Granata75dfb432013-02-15 00:06:04 +00001233 if (!valobj_sp)
1234 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001235
1236 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1237 return true;
1238}
1239
Enrico Granata6d37cc62013-03-19 00:27:22 +00001240// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1241// this call gives the POSIX equivalent of the Cocoa epoch
1242time_t
Enrico Granata92373532013-03-19 22:58:48 +00001243lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001244{
1245 static time_t epoch = 0;
1246 if (!epoch)
1247 {
1248 tzset();
1249 tm tm_epoch;
1250 tm_epoch.tm_sec = 0;
1251 tm_epoch.tm_hour = 0;
1252 tm_epoch.tm_min = 0;
1253 tm_epoch.tm_mon = 0;
1254 tm_epoch.tm_mday = 1;
1255 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1256 tm_epoch.tm_isdst = -1;
1257 tm_epoch.tm_gmtoff = 0;
1258 tm_epoch.tm_zone = NULL;
1259 epoch = timegm(&tm_epoch);
1260 }
1261 return epoch;
1262}
1263
Greg Claytonc7bece562013-01-25 18:06:21 +00001264size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001265lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001266{
1267 if (!item_name || !*item_name)
1268 return UINT32_MAX;
1269 if (*item_name != '[')
1270 return UINT32_MAX;
1271 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001272 char* endptr = NULL;
1273 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1274 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001275 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001276 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001277 return UINT32_MAX;
1278 return idx;
1279}
1280
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001281lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1282 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001283SyntheticChildrenFrontEnd(*valobj_sp.get()),
1284m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001285m_item_name(item_name),
1286m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001287{
1288 if (valobj_sp)
1289 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001290}
1291
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001292bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001293lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001294{
Enrico Granata6eca3552013-03-28 18:50:54 +00001295 m_item_sp.reset();
1296
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001297 ValueObjectSP valobj_sp = m_backend.GetSP();
1298 if (!valobj_sp)
1299 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001300
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001301 if (!valobj_sp)
1302 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001303
1304 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1305 if (!item_ptr)
1306 return false;
1307 if (item_ptr->GetValueAsUnsigned(0) == 0)
1308 return false;
1309 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001310 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001311 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
1312 if (err.Fail())
1313 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001314 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001315}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001316
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001317size_t
1318lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1319{
1320 return 1;
1321}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001322
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001323lldb::ValueObjectSP
1324lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1325{
1326 if (idx == 0)
1327 return m_item_sp;
1328 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001329}
1330
1331bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001332lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001333{
1334 return true;
1335}
1336
1337size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001338lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001339{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001340 if (name == ConstString("item"))
1341 return 0;
1342 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001343}
1344
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001345lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001346{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001347}
1348
Enrico Granataf5196282012-09-04 18:48:21 +00001349template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001350lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1351
1352template bool
1353lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001354
1355template bool
1356lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1357
1358template bool
1359lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;