blob: b1d0f7d5f5be5b61de4c9dfac80f6d7f98f30ede [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 Granataa3962a72013-05-15 00:47:46 +0000657// the field layout in a libc++ string (cap, side, data or data, size, cap)
658enum LibcxxStringLayoutMode
659{
660 eLibcxxStringLayoutModeCSD = 0,
661 eLibcxxStringLayoutModeDSC = 1,
662 eLibcxxStringLayoutModeInvalid = 0xffff
663};
664
665// this function abstracts away the layout and mode details of a libc++ string
666// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000667static bool
668ExtractLibcxxStringInfo (ValueObject& valobj,
669 ValueObjectSP &location_sp,
670 uint64_t& size)
671{
672 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
673 if (!D)
674 return false;
675
Enrico Granataa3962a72013-05-15 00:47:46 +0000676 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
677
678 // this child should exist
679 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000680 return false;
681
Enrico Granataa3962a72013-05-15 00:47:46 +0000682 ConstString g_data_name("__data_");
683 ConstString g_size_name("__size_");
684 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
685 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
686 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000687
Enrico Granataa3962a72013-05-15 00:47:46 +0000688 if (layout == eLibcxxStringLayoutModeDSC)
689 {
690 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
691 if (!size_mode)
692 return false;
693
694 if (size_mode->GetName() != g_size_name)
695 {
696 // we are hitting the padding structure, move along
697 size_mode = D->GetChildAtIndexPath({1,1,1});
698 if (!size_mode)
699 return false;
700 }
701
702 size_mode_value = (size_mode->GetValueAsUnsigned(0));
703 short_mode = ((size_mode_value & 0x80) == 0);
704 }
705 else
706 {
707 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
708 if (!size_mode)
709 return false;
710
711 size_mode_value = (size_mode->GetValueAsUnsigned(0));
712 short_mode = ((size_mode_value & 1) == 0);
713 }
714
715 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000716 {
717 ValueObjectSP s(D->GetChildAtIndex(1, true));
718 if (!s)
719 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000720 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
721 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000722 return (location_sp.get() != nullptr);
723 }
724 else
725 {
726 ValueObjectSP l(D->GetChildAtIndex(0, true));
727 if (!l)
728 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000729 // we can use the layout_decider object as the data pointer
730 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000731 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
732 if (!size_vo || !location_sp)
733 return false;
734 size = size_vo->GetValueAsUnsigned(0);
735 return true;
736 }
737}
738
739bool
740lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
741{
742 uint64_t size = 0;
743 ValueObjectSP location_sp((ValueObject*)nullptr);
744 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
745 return false;
746 if (size == 0)
747 {
748 stream.Printf("L\"\"");
749 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000750 }
Enrico Granata3309d882013-01-12 01:00:22 +0000751 if (!location_sp)
752 return false;
753 return WCharStringSummaryProvider(*location_sp.get(), stream);
754}
755
756bool
757lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
758{
759 uint64_t size = 0;
760 ValueObjectSP location_sp((ValueObject*)nullptr);
761 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
762 return false;
763 if (size == 0)
764 {
765 stream.Printf("\"\"");
766 return true;
767 }
768 if (!location_sp)
769 return false;
770 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000771 if (location_sp->ReadPointedString(stream,
772 error,
773 0, // max length is decided by the settings
774 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
775 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000776 return error.Success();
777}
778
Enrico Granata55900862013-03-15 18:55:30 +0000779bool
780lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
781{
782 ProcessSP process_sp = valobj.GetProcessSP();
783 if (!process_sp)
784 return false;
785
786 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
787
788 if (!runtime)
789 return false;
790
Greg Clayton03da4cc2013-04-19 21:31:16 +0000791 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000792
793 if (!descriptor.get() || !descriptor->IsValid())
794 return false;
795
796 const char* class_name = descriptor->GetClassName().GetCString();
797
798 if (!class_name || !*class_name)
799 return false;
800
801 stream.Printf("%s",class_name);
802 return true;
803}
804
Enrico Granatac76b97b2013-04-26 00:59:02 +0000805class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
806{
807public:
808 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
809 SyntheticChildrenFrontEnd(*valobj_sp.get())
810 {
811 }
812
813 virtual size_t
814 CalculateNumChildren ()
815 {
816 return 0;
817 }
818
819 virtual lldb::ValueObjectSP
820 GetChildAtIndex (size_t idx)
821 {
822 return lldb::ValueObjectSP();
823 }
824
825 virtual bool
826 Update()
827 {
828 return false;
829 }
830
831 virtual bool
832 MightHaveChildren ()
833 {
834 return false;
835 }
836
837 virtual size_t
838 GetIndexOfChildWithName (const ConstString &name)
839 {
840 return UINT32_MAX;
841 }
842
843 virtual
844 ~ObjCClassSyntheticChildrenFrontEnd ()
845 {
846 }
847};
848
849SyntheticChildrenFrontEnd*
850lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
851{
852 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
853}
854
Enrico Granataf5196282012-09-04 18:48:21 +0000855template<bool needs_at>
856bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000857lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000858{
859 ProcessSP process_sp = valobj.GetProcessSP();
860 if (!process_sp)
861 return false;
862
863 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
864
865 if (!runtime)
866 return false;
867
868 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
869
870 if (!descriptor.get() || !descriptor->IsValid())
871 return false;
872
873 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
874 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
875
876 if (!valobj_addr)
877 return false;
878
879 uint64_t value = 0;
880
881 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000882
883 if (!class_name || !*class_name)
884 return false;
885
Enrico Granataf5196282012-09-04 18:48:21 +0000886 if (!strcmp(class_name,"NSConcreteData") ||
887 !strcmp(class_name,"NSConcreteMutableData") ||
888 !strcmp(class_name,"__NSCFData"))
889 {
890 uint32_t offset = (is_64bit ? 16 : 8);
891 Error error;
892 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
893 if (error.Fail())
894 return false;
895 }
896 else
897 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000898 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000899 return false;
900 }
901
Daniel Malead01b2952012-11-29 21:49:15 +0000902 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000903 (needs_at ? "@\"" : ""),
904 value,
905 (value > 1 ? "s" : ""),
906 (needs_at ? "\"" : ""));
907
908 return true;
909}
910
Enrico Granata87f00b42013-02-21 20:31:18 +0000911static bool
912ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
913 lldb::ProcessSP& process_sp,
914 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000915 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000916 Error* error = NULL,
917 size_t *data_read = NULL,
918 char prefix_token = '@',
919 char quote = '"')
920{
921 Error my_error;
922 size_t my_data_read;
923 if (!process_sp || location == 0)
924 return false;
925
Enrico Granata23ab35a2013-04-02 23:07:55 +0000926 if (!size)
927 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
928 else
929 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000930
931 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
932
933 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
934
935 if (error)
936 *error = my_error;
937 if (data_read)
938 *data_read = my_data_read;
939
940 if (my_error.Fail())
941 return false;
942 if (my_data_read)
943 dest.Printf("%c%c%s%c",prefix_token,quote,(char*)buffer_sp->GetBytes(),quote);
944
945 return true;
946}
947
Enrico Granatad83bfce2013-04-02 21:25:34 +0000948#ifdef WANT_DEEP_PRINT
949struct lldb__notInlineMutable {
950 void *buffer;
951 signed long length;
952 signed long capacity;
953 unsigned int hasGap:1;
954 unsigned int isFixedCapacity:1;
955 unsigned int isExternalMutable:1;
956 unsigned int capacityProvidedExternally:1;
957#if __LP64__
958 unsigned long desiredCapacity:60;
959#else
960 unsigned long desiredCapacity:28;
961#endif
962 void* contentsAllocator;
963};
964
965struct lldb__CFString {
966 uintptr_t _cfisa;
967 uint8_t _cfinfo[4];
968 uint32_t _rc;
969 union {
970 struct __inline1 {
971 signed long length;
972 } inline1;
973 struct __notInlineImmutable1 {
974 void *buffer;
975 signed long length;
976 void* contentsDeallocator;
977 } notInlineImmutable1;
978 struct __notInlineImmutable2 {
979 void *buffer;
980 void* contentsDeallocator;
981 } notInlineImmutable2;
982 struct lldb__notInlineMutable notInlineMutable;
983 } variants;
984};
985#endif
986
Enrico Granataf5196282012-09-04 18:48:21 +0000987bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000988lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000989{
990 ProcessSP process_sp = valobj.GetProcessSP();
991 if (!process_sp)
992 return false;
993
994 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
995
996 if (!runtime)
997 return false;
998
999 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
1000
1001 if (!descriptor.get() || !descriptor->IsValid())
1002 return false;
1003
1004 uint32_t ptr_size = process_sp->GetAddressByteSize();
1005
1006 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1007
1008 if (!valobj_addr)
1009 return false;
1010
1011 const char* class_name = descriptor->GetClassName().GetCString();
1012
Enrico Granata60b81df2012-09-29 00:45:53 +00001013 if (!class_name || !*class_name)
1014 return false;
1015
Enrico Granataf5196282012-09-04 18:48:21 +00001016 uint64_t info_bits_location = valobj_addr + ptr_size;
1017 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
1018 info_bits_location += 3;
1019
Enrico Granata87f00b42013-02-21 20:31:18 +00001020 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +00001021
1022 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
1023 if (error.Fail())
1024 return false;
1025
1026 bool is_mutable = (info_bits & 1) == 1;
1027 bool is_inline = (info_bits & 0x60) == 0;
1028 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
1029 bool is_unicode = (info_bits & 0x10) == 0x10;
1030 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001031 bool has_null = (info_bits & 8) == 8;
1032
1033 size_t explicit_length = 0;
1034 if (!has_null && has_explicit_length && !is_special)
1035 {
1036 lldb::addr_t explicit_length_offset = 2*ptr_size;
1037 if (is_mutable and not is_inline)
1038 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1039 else if (is_inline)
1040 explicit_length = explicit_length + 0; // inline1.length;
1041 else if (not is_inline and not is_mutable)
1042 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1043 else
1044 explicit_length_offset = 0;
1045
1046 if (explicit_length_offset)
1047 {
1048 explicit_length_offset = valobj_addr + explicit_length_offset;
1049 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1050 }
1051 }
1052
1053#ifdef WANT_DEEP_PRINT
1054 lldb__CFString my_string_data;
1055 process_sp->ReadMemory(valobj_addr, &my_string_data, sizeof(lldb__CFString),error);
1056
1057 printf(R"(
1058 __CFString my_string_data = {
1059 uintptr_t _cfisa = %lu
1060 uint8_t _cfinfo[4] = %c%c%c%c
1061 uint32_t _rc = %d
1062 union {
1063 struct __inline1 {
1064 signed long length = %ld
1065 } inline1;
1066 struct __notInlineImmutable1 {
1067 void *buffer = %p
1068 signed long length = %ld
1069 void* contentsDeallocator = %p
1070 } notInlineImmutable1;
1071 struct __notInlineImmutable2 {
1072 void *buffer = %p
1073 void* contentsDeallocator = %p
1074 } notInlineImmutable2;
1075 struct __notInlineMutable notInlineMutable {
1076 void *buffer = %p
1077 signed long length = %ld
1078 signed long capacity = %ld
1079 unsigned int hasGap:1 = %d
1080 unsigned int isFixedCapacity:1 = %d
1081 unsigned int isExternalMutable:1 = %d
1082 unsigned int capacityProvidedExternally:1 = %d
1083#if __LP64__
1084 unsigned long desiredCapacity:60 = %lu
1085#else
1086 unsigned long desiredCapacity:28 = %lu
1087#endif
1088 void* contentsAllocator = %p
1089 }
Enrico Granata56768392013-04-23 20:05:05 +00001090 } variants; ==> (M:%dI:%dL:%zuU:%dS:%dN:%d)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001091 };\n)",
1092 my_string_data._cfisa,
1093 my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
1094 my_string_data._rc,
1095 my_string_data.variants.inline1.length,
1096 my_string_data.variants.notInlineImmutable1.buffer,
1097 my_string_data.variants.notInlineImmutable1.length,
1098 my_string_data.variants.notInlineImmutable1.contentsDeallocator,
1099 my_string_data.variants.notInlineImmutable2.buffer,
1100 my_string_data.variants.notInlineImmutable2.contentsDeallocator,
1101 my_string_data.variants.notInlineMutable.buffer,
1102 my_string_data.variants.notInlineMutable.length,
1103 my_string_data.variants.notInlineMutable.capacity,
1104 my_string_data.variants.notInlineMutable.hasGap,
1105 my_string_data.variants.notInlineMutable.isFixedCapacity,
1106 my_string_data.variants.notInlineMutable.isExternalMutable,
1107 my_string_data.variants.notInlineMutable.capacityProvidedExternally,
1108 my_string_data.variants.notInlineMutable.desiredCapacity,
1109 my_string_data.variants.notInlineMutable.desiredCapacity,
Enrico Granata56768392013-04-23 20:05:05 +00001110 my_string_data.variants.notInlineMutable.contentsAllocator,
1111 is_mutable,
1112 is_inline,
1113 explicit_length,
1114 is_unicode,
1115 is_special,
1116 has_null);
Enrico Granatad83bfce2013-04-02 21:25:34 +00001117#endif
Enrico Granataf5196282012-09-04 18:48:21 +00001118
1119 if (strcmp(class_name,"NSString") &&
1120 strcmp(class_name,"CFStringRef") &&
1121 strcmp(class_name,"CFMutableStringRef") &&
1122 strcmp(class_name,"__NSCFConstantString") &&
1123 strcmp(class_name,"__NSCFString") &&
1124 strcmp(class_name,"NSCFConstantString") &&
1125 strcmp(class_name,"NSCFString") &&
1126 strcmp(class_name,"NSPathStore2"))
1127 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001128 // not one of us - but tell me class name
1129 stream.Printf("class name = %s",class_name);
1130 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001131 }
1132
1133 if (is_mutable)
1134 {
1135 uint64_t location = 2 * ptr_size + valobj_addr;
1136 location = process_sp->ReadPointerFromMemory(location, error);
1137 if (error.Fail())
1138 return false;
1139 if (has_explicit_length and is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001140 {
1141 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1142 options.SetConversionFunction(ConvertUTF16toUTF8);
1143 options.SetLocation(location);
1144 options.SetProcessSP(process_sp);
1145 options.SetStream(&stream);
1146 options.SetPrefixToken('@');
1147 options.SetQuote('"');
1148 options.SetSourceSize(explicit_length);
1149 options.SetNeedsZeroTermination(false);
1150 return ReadUTFBufferAndDumpToStream (options);
1151 }
Enrico Granataf5196282012-09-04 18:48:21 +00001152 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001153 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001154 }
1155 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1156 {
1157 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001158 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001159 }
1160 else if (is_unicode)
1161 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001162 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001163 if (is_inline)
1164 {
1165 if (!has_explicit_length)
1166 {
1167 stream.Printf("found new combo");
1168 return true;
1169 }
1170 else
1171 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001172 }
Enrico Granataf5196282012-09-04 18:48:21 +00001173 else
1174 {
1175 location = process_sp->ReadPointerFromMemory(location, error);
1176 if (error.Fail())
1177 return false;
1178 }
Enrico Granata56768392013-04-23 20:05:05 +00001179 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1180 options.SetConversionFunction(ConvertUTF16toUTF8);
1181 options.SetLocation(location);
1182 options.SetProcessSP(process_sp);
1183 options.SetStream(&stream);
1184 options.SetPrefixToken('@');
1185 options.SetQuote('"');
1186 options.SetSourceSize(explicit_length);
1187 options.SetNeedsZeroTermination(has_explicit_length == false);
1188 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001189 }
1190 else if (is_special)
1191 {
1192 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001193 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1194 options.SetConversionFunction(ConvertUTF16toUTF8);
1195 options.SetLocation(location);
1196 options.SetProcessSP(process_sp);
1197 options.SetStream(&stream);
1198 options.SetPrefixToken('@');
1199 options.SetQuote('"');
1200 options.SetSourceSize(explicit_length);
1201 options.SetNeedsZeroTermination(has_explicit_length == false);
1202 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001203 }
1204 else if (is_inline)
1205 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001206 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001207 if (!has_explicit_length)
1208 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001209 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001210 }
1211 else
1212 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001213 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001214 location = process_sp->ReadPointerFromMemory(location, error);
1215 if (error.Fail())
1216 return false;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001217 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001218 }
1219
1220 stream.Printf("class name = %s",class_name);
1221 return true;
1222
1223}
1224
Enrico Granataf175ad12012-10-03 23:53:45 +00001225bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001226lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1227{
1228 TargetSP target_sp(valobj.GetTargetSP());
1229 if (!target_sp)
1230 return false;
1231 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1232 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1233 if (!pointee)
1234 return false;
1235 pointee += addr_size;
1236 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1237 ExecutionContext exe_ctx(target_sp,false);
1238 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1239 if (!child_ptr_sp)
1240 return false;
1241 DataExtractor data;
1242 child_ptr_sp->GetData(data);
1243 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1244 child_sp->GetValueAsUnsigned(0);
1245 if (child_sp)
1246 return NSStringSummaryProvider(*child_sp, stream);
1247 return false;
1248}
1249
1250bool
1251lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1252{
1253 return NSAttributedStringSummaryProvider(valobj, stream);
1254}
1255
1256bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001257lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1258{
1259 stream.Printf("%s",valobj.GetObjectDescription());
1260 return true;
1261}
1262
Enrico Granatab5887262012-10-29 21:18:03 +00001263bool
1264lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1265{
1266 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1267 valobj.GetClangAST(),
1268 NULL);
1269
1270 ValueObjectSP real_guy_sp = valobj.GetSP();
1271
1272 if (type_info & ClangASTContext::eTypeIsPointer)
1273 {
1274 Error err;
1275 real_guy_sp = valobj.Dereference(err);
1276 if (err.Fail() || !real_guy_sp)
1277 return false;
1278 }
1279 else if (type_info & ClangASTContext::eTypeIsReference)
1280 {
1281 real_guy_sp = valobj.GetChildAtIndex(0, true);
1282 if (!real_guy_sp)
1283 return false;
1284 }
1285 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1286 if (value == 0)
1287 {
1288 stream.Printf("NO");
1289 return true;
1290 }
1291 stream.Printf("YES");
1292 return true;
1293}
1294
1295template <bool is_sel_ptr>
1296bool
1297lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1298{
Enrico Granata75dfb432013-02-15 00:06:04 +00001299 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001300
Enrico Granata75dfb432013-02-15 00:06:04 +00001301 if (!valobj.GetClangAST())
Enrico Granatab5887262012-10-29 21:18:03 +00001302 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001303 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1304 if (!char_opaque_type)
1305 return false;
1306 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1307
Enrico Granatab5887262012-10-29 21:18:03 +00001308 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1309
Enrico Granata75dfb432013-02-15 00:06:04 +00001310 if (is_sel_ptr)
1311 {
1312 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1313 if (data_address == LLDB_INVALID_ADDRESS)
1314 return false;
1315 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1316 }
1317 else
1318 {
1319 DataExtractor data;
1320 valobj.GetData(data);
1321 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1322 }
Enrico Granatab5887262012-10-29 21:18:03 +00001323
Enrico Granata75dfb432013-02-15 00:06:04 +00001324 if (!valobj_sp)
1325 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001326
1327 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1328 return true;
1329}
1330
Enrico Granata6d37cc62013-03-19 00:27:22 +00001331// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1332// this call gives the POSIX equivalent of the Cocoa epoch
1333time_t
Enrico Granata92373532013-03-19 22:58:48 +00001334lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001335{
1336 static time_t epoch = 0;
1337 if (!epoch)
1338 {
1339 tzset();
1340 tm tm_epoch;
1341 tm_epoch.tm_sec = 0;
1342 tm_epoch.tm_hour = 0;
1343 tm_epoch.tm_min = 0;
1344 tm_epoch.tm_mon = 0;
1345 tm_epoch.tm_mday = 1;
1346 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1347 tm_epoch.tm_isdst = -1;
1348 tm_epoch.tm_gmtoff = 0;
1349 tm_epoch.tm_zone = NULL;
1350 epoch = timegm(&tm_epoch);
1351 }
1352 return epoch;
1353}
1354
Greg Claytonc7bece562013-01-25 18:06:21 +00001355size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001356lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001357{
1358 if (!item_name || !*item_name)
1359 return UINT32_MAX;
1360 if (*item_name != '[')
1361 return UINT32_MAX;
1362 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001363 char* endptr = NULL;
1364 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1365 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001366 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001367 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001368 return UINT32_MAX;
1369 return idx;
1370}
1371
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001372lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1373 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001374SyntheticChildrenFrontEnd(*valobj_sp.get()),
1375m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001376m_item_name(item_name),
1377m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001378{
1379 if (valobj_sp)
1380 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001381}
1382
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001383bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001384lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001385{
Enrico Granata6eca3552013-03-28 18:50:54 +00001386 m_item_sp.reset();
1387
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001388 ValueObjectSP valobj_sp = m_backend.GetSP();
1389 if (!valobj_sp)
1390 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001391
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001392 if (!valobj_sp)
1393 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001394
1395 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1396 if (!item_ptr)
1397 return false;
1398 if (item_ptr->GetValueAsUnsigned(0) == 0)
1399 return false;
1400 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001401 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001402 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
1403 if (err.Fail())
1404 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001405 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001406}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001407
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001408size_t
1409lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1410{
1411 return 1;
1412}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001413
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001414lldb::ValueObjectSP
1415lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1416{
1417 if (idx == 0)
1418 return m_item_sp;
1419 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001420}
1421
1422bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001423lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001424{
1425 return true;
1426}
1427
1428size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001429lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001430{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001431 if (name == ConstString("item"))
1432 return 0;
1433 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001434}
1435
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001436lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001437{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001438}
1439
Enrico Granataf5196282012-09-04 18:48:21 +00001440template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001441lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1442
1443template bool
1444lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001445
1446template bool
1447lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1448
1449template bool
1450lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;