blob: 348186f55e4d579a032dba7425233cf32dd120b9 [file] [log] [blame]
Enrico Granataf5196282012-09-04 18:48:21 +00001//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Matt Kopecef143712013-06-03 18:00:07 +000010#include "lldb/lldb-python.h"
11
Enrico Granata5548cb52013-01-28 23:47:25 +000012#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granataf5196282012-09-04 18:48:21 +000013
Dmitri Gribenko024aa852013-01-30 15:05:59 +000014#include "llvm/Support/ConvertUTF.h"
Enrico Granataf5196282012-09-04 18:48:21 +000015
Enrico Granatab2698cd2012-09-13 18:27:09 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/Error.h"
Enrico Granataf5196282012-09-04 18:48:21 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/ValueObject.h"
Enrico Granatab2698cd2012-09-13 18:27:09 +000020#include "lldb/Core/ValueObjectConstResult.h"
21#include "lldb/Host/Endian.h"
Enrico Granatab5887262012-10-29 21:18:03 +000022#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataf5196282012-09-04 18:48:21 +000023#include "lldb/Target/ObjCLanguageRuntime.h"
24#include "lldb/Target/Target.h"
25
Enrico Granatad83bfce2013-04-02 21:25:34 +000026#include <algorithm>
27
Enrico Granataf5196282012-09-04 18:48:21 +000028using namespace lldb;
29using namespace lldb_private;
30using namespace lldb_private::formatters;
31
32bool
Enrico Granatab2698cd2012-09-13 18:27:09 +000033lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
34 const char* target_type,
35 const char* selector,
36 uint64_t &value)
Enrico Granataf5196282012-09-04 18:48:21 +000037{
38 if (!target_type || !*target_type)
39 return false;
40 if (!selector || !*selector)
41 return false;
Enrico Granataf5196282012-09-04 18:48:21 +000042 StreamString expr;
Daniel Maleaa85e6b62012-12-07 22:21:08 +000043 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf5196282012-09-04 18:48:21 +000044 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
45 lldb::ValueObjectSP result_sp;
46 Target* target = exe_ctx.GetTargetPtr();
47 StackFrame* stack_frame = exe_ctx.GetFramePtr();
48 if (!target || !stack_frame)
49 return false;
Enrico Granatad4439aa2012-09-05 20:41:26 +000050
Jim Ingham35e1bda2012-10-16 21:41:58 +000051 EvaluateExpressionOptions options;
Enrico Granatad4439aa2012-09-05 20:41:26 +000052 options.SetCoerceToId(false)
53 .SetUnwindOnError(true)
Sean Callananc7cb3142012-12-04 20:56:04 +000054 .SetKeepInMemory(true);
Enrico Granatad4439aa2012-09-05 20:41:26 +000055
Enrico Granataf5196282012-09-04 18:48:21 +000056 target->EvaluateExpression(expr.GetData(),
57 stack_frame,
Enrico Granatad4439aa2012-09-05 20:41:26 +000058 result_sp,
59 options);
Enrico Granataf5196282012-09-04 18:48:21 +000060 if (!result_sp)
61 return false;
62 value = result_sp->GetValueAsUnsigned(0);
63 return true;
64}
65
Enrico Granataf615b802013-02-15 23:38:37 +000066bool
67lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
68 const char* target_type,
69 const char* selector,
70 Stream &stream)
71{
72 if (!target_type || !*target_type)
73 return false;
74 if (!selector || !*selector)
75 return false;
76 StreamString expr;
Enrico Granataeac4a482013-02-19 01:14:06 +000077 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataf615b802013-02-15 23:38:37 +000078 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
79 lldb::ValueObjectSP result_sp;
80 Target* target = exe_ctx.GetTargetPtr();
81 StackFrame* stack_frame = exe_ctx.GetFramePtr();
82 if (!target || !stack_frame)
83 return false;
84
85 EvaluateExpressionOptions options;
86 options.SetCoerceToId(false)
87 .SetUnwindOnError(true)
88 .SetKeepInMemory(true)
89 .SetUseDynamic(lldb::eDynamicCanRunTarget);
90
91 target->EvaluateExpression(expr.GetData(),
92 stack_frame,
93 result_sp,
94 options);
95 if (!result_sp)
96 return false;
97 stream.Printf("%s",result_sp->GetSummaryAsCString());
98 return true;
99}
100
Enrico Granatab2698cd2012-09-13 18:27:09 +0000101lldb::ValueObjectSP
102lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
103 const char* return_type,
104 const char* selector,
105 uint64_t index)
106{
107 lldb::ValueObjectSP valobj_sp;
108 if (!return_type || !*return_type)
109 return valobj_sp;
110 if (!selector || !*selector)
111 return valobj_sp;
112 StreamString expr_path_stream;
113 valobj.GetExpressionPath(expr_path_stream, false);
114 StreamString expr;
Daniel Malead01b2952012-11-29 21:49:15 +0000115 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granatab2698cd2012-09-13 18:27:09 +0000116 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
117 lldb::ValueObjectSP result_sp;
118 Target* target = exe_ctx.GetTargetPtr();
119 StackFrame* stack_frame = exe_ctx.GetFramePtr();
120 if (!target || !stack_frame)
121 return valobj_sp;
122
Jim Ingham35e1bda2012-10-16 21:41:58 +0000123 EvaluateExpressionOptions options;
Enrico Granatab2698cd2012-09-13 18:27:09 +0000124 options.SetCoerceToId(false)
125 .SetUnwindOnError(true)
126 .SetKeepInMemory(true)
127 .SetUseDynamic(lldb::eDynamicCanRunTarget);
128
129 target->EvaluateExpression(expr.GetData(),
130 stack_frame,
131 valobj_sp,
132 options);
133 return valobj_sp;
134}
135
136lldb::ValueObjectSP
137lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
138 const char* return_type,
139 const char* selector,
140 const char* key)
141{
142 lldb::ValueObjectSP valobj_sp;
143 if (!return_type || !*return_type)
144 return valobj_sp;
145 if (!selector || !*selector)
146 return valobj_sp;
147 if (!key || !*key)
148 return valobj_sp;
149 StreamString expr_path_stream;
150 valobj.GetExpressionPath(expr_path_stream, false);
151 StreamString expr;
152 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
153 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
154 lldb::ValueObjectSP result_sp;
155 Target* target = exe_ctx.GetTargetPtr();
156 StackFrame* stack_frame = exe_ctx.GetFramePtr();
157 if (!target || !stack_frame)
158 return valobj_sp;
159
Jim Ingham35e1bda2012-10-16 21:41:58 +0000160 EvaluateExpressionOptions options;
Enrico Granatab2698cd2012-09-13 18:27:09 +0000161 options.SetCoerceToId(false)
162 .SetUnwindOnError(true)
163 .SetKeepInMemory(true)
164 .SetUseDynamic(lldb::eDynamicCanRunTarget);
165
166 target->EvaluateExpression(expr.GetData(),
167 stack_frame,
168 valobj_sp,
169 options);
170 return valobj_sp;
171}
172
Enrico Granata93d59662013-01-14 23:53:26 +0000173// use this call if you already have an LLDB-side buffer for the data
174template<typename SourceDataType>
Enrico Granataf68df122013-01-10 22:08:35 +0000175static bool
Enrico Granata93d59662013-01-14 23:53:26 +0000176DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
177 const SourceDataType*,
178 UTF8**,
179 UTF8*,
180 ConversionFlags),
181 DataExtractor& data,
182 Stream& stream,
183 char prefix_token = '@',
184 char quote = '"',
Enrico Granatad83bfce2013-04-02 21:25:34 +0000185 uint32_t sourceSize = 0)
Enrico Granataf68df122013-01-10 22:08:35 +0000186{
Enrico Granata93d59662013-01-14 23:53:26 +0000187 if (prefix_token != 0)
188 stream.Printf("%c",prefix_token);
189 if (quote != 0)
190 stream.Printf("%c",quote);
191 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf68df122013-01-10 22:08:35 +0000192 {
Enrico Granata93d59662013-01-14 23:53:26 +0000193 const int bufferSPSize = data.GetByteSize();
194 if (sourceSize == 0)
195 {
196 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Claytonaa4c47a2013-02-08 21:59:34 +0000197 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granata93d59662013-01-14 23:53:26 +0000198 }
199
200 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000201 SourceDataType *data_end_ptr = data_ptr + sourceSize;
202
203 while (data_ptr < data_end_ptr)
204 {
205 if (!*data_ptr)
206 {
207 data_end_ptr = data_ptr;
208 break;
209 }
210 data_ptr++;
211 }
212
Enrico Granata93d59662013-01-14 23:53:26 +0000213 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf68df122013-01-10 22:08:35 +0000214
Enrico Granata38352042013-01-11 02:44:00 +0000215 lldb::DataBufferSP utf8_data_buffer_sp;
216 UTF8* utf8_data_ptr = nullptr;
217 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granata93d59662013-01-14 23:53:26 +0000218
Enrico Granataf68df122013-01-10 22:08:35 +0000219 if (ConvertFunction)
Enrico Granata38352042013-01-11 02:44:00 +0000220 {
Enrico Granata56768392013-04-23 20:05:05 +0000221 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
Enrico Granata38352042013-01-11 02:44:00 +0000222 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
Enrico Granata56768392013-04-23 20:05:05 +0000223 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
Enrico Granataf68df122013-01-10 22:08:35 +0000224 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata38352042013-01-11 02:44:00 +0000225 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
226 }
Enrico Granataf68df122013-01-10 22:08:35 +0000227 else
228 {
229 // just copy the pointers - the cast is necessary to make the compiler happy
230 // but this should only happen if we are reading UTF8 data
231 utf8_data_ptr = (UTF8*)data_ptr;
232 utf8_data_end_ptr = (UTF8*)data_end_ptr;
233 }
234
Enrico Granata3309d882013-01-12 01:00:22 +0000235 // since we tend to accept partial data (and even partially malformed data)
236 // we might end up with no NULL terminator before the end_ptr
237 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf68df122013-01-10 22:08:35 +0000238 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
239 {
240 if (!*utf8_data_ptr)
241 break;
242 stream.Printf("%c",*utf8_data_ptr);
243 }
Enrico Granata93d59662013-01-14 23:53:26 +0000244 }
245 if (quote != 0)
246 stream.Printf("%c",quote);
247 return true;
248}
249
250template<typename SourceDataType>
Enrico Granata56768392013-04-23 20:05:05 +0000251class ReadUTFBufferAndDumpToStreamOptions
Enrico Granata93d59662013-01-14 23:53:26 +0000252{
Enrico Granata56768392013-04-23 20:05:05 +0000253public:
254 typedef ConversionResult (*ConvertFunctionType) (const SourceDataType**,
255 const SourceDataType*,
256 UTF8**,
257 UTF8*,
258 ConversionFlags);
259
260 ReadUTFBufferAndDumpToStreamOptions () :
261 m_conversion_function(NULL),
262 m_location(0),
263 m_process_sp(),
264 m_stream(NULL),
265 m_prefix_token('@'),
266 m_quote('"'),
267 m_source_size(0),
268 m_needs_zero_termination(true)
269 {
270 }
271
272 ReadUTFBufferAndDumpToStreamOptions&
273 SetConversionFunction (ConvertFunctionType f)
274 {
275 m_conversion_function = f;
276 return *this;
277 }
278
279 ConvertFunctionType
280 GetConversionFunction () const
281 {
282 return m_conversion_function;
283 }
284
285 ReadUTFBufferAndDumpToStreamOptions&
286 SetLocation (uint64_t l)
287 {
288 m_location = l;
289 return *this;
290 }
291
292 uint64_t
293 GetLocation () const
294 {
295 return m_location;
296 }
297
298 ReadUTFBufferAndDumpToStreamOptions&
299 SetProcessSP (ProcessSP p)
300 {
301 m_process_sp = p;
302 return *this;
303 }
304
305 ProcessSP
306 GetProcessSP () const
307 {
308 return m_process_sp;
309 }
310
311 ReadUTFBufferAndDumpToStreamOptions&
312 SetStream (Stream* s)
313 {
314 m_stream = s;
315 return *this;
316 }
317
318 Stream*
319 GetStream () const
320 {
321 return m_stream;
322 }
323
324 ReadUTFBufferAndDumpToStreamOptions&
325 SetPrefixToken (char p)
326 {
327 m_prefix_token = p;
328 return *this;
329 }
330
331 char
332 GetPrefixToken () const
333 {
334 return m_prefix_token;
335 }
336
337 ReadUTFBufferAndDumpToStreamOptions&
338 SetQuote (char q)
339 {
340 m_quote = q;
341 return *this;
342 }
343
344 char
345 GetQuote () const
346 {
347 return m_quote;
348 }
349
350 ReadUTFBufferAndDumpToStreamOptions&
351 SetSourceSize (uint32_t s)
352 {
353 m_source_size = s;
354 return *this;
355 }
356
357 uint32_t
358 GetSourceSize () const
359 {
360 return m_source_size;
361 }
362
363 ReadUTFBufferAndDumpToStreamOptions&
364 SetNeedsZeroTermination (bool z)
365 {
366 m_needs_zero_termination = z;
367 return *this;
368 }
369
370 bool
371 GetNeedsZeroTermination () const
372 {
373 return m_needs_zero_termination;
374 }
375
376private:
377 ConvertFunctionType m_conversion_function;
378 uint64_t m_location;
379 ProcessSP m_process_sp;
380 Stream* m_stream;
381 char m_prefix_token;
382 char m_quote;
383 uint32_t m_source_size;
384 bool m_needs_zero_termination;
385};
386
387template<typename SourceDataType>
388static bool
389ReadUTFBufferAndDumpToStream (const ReadUTFBufferAndDumpToStreamOptions<SourceDataType>& options)
390{
391 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
Enrico Granata93d59662013-01-14 23:53:26 +0000392 return false;
Enrico Granata56768392013-04-23 20:05:05 +0000393
394 ProcessSP process_sp(options.GetProcessSP());
395
Enrico Granata93d59662013-01-14 23:53:26 +0000396 if (!process_sp)
397 return false;
398
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000399 const int type_width = sizeof(SourceDataType);
400 const int origin_encoding = 8 * type_width ;
Enrico Granata93d59662013-01-14 23:53:26 +0000401 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
402 return false;
403 // if not UTF8, I need a conversion function to return proper UTF8
Enrico Granata56768392013-04-23 20:05:05 +0000404 if (origin_encoding != 8 && !options.GetConversionFunction())
405 return false;
406
407 if (!options.GetStream())
Enrico Granata93d59662013-01-14 23:53:26 +0000408 return false;
409
Enrico Granata56768392013-04-23 20:05:05 +0000410 uint32_t sourceSize = options.GetSourceSize();
411 bool needs_zero_terminator = options.GetNeedsZeroTermination();
412
Enrico Granata23ab35a2013-04-02 23:07:55 +0000413 if (!sourceSize)
Enrico Granata56768392013-04-23 20:05:05 +0000414 {
Enrico Granata23ab35a2013-04-02 23:07:55 +0000415 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
Enrico Granata56768392013-04-23 20:05:05 +0000416 needs_zero_terminator = true;
417 }
Enrico Granata23ab35a2013-04-02 23:07:55 +0000418 else
419 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
420
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000421 const int bufferSPSize = sourceSize * type_width;
Enrico Granata93d59662013-01-14 23:53:26 +0000422
Enrico Granata93d59662013-01-14 23:53:26 +0000423 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
424
425 if (!buffer_sp->GetBytes())
426 return false;
427
Ashok Thirumurthi6ac9d132013-04-19 15:58:38 +0000428 Error error;
429 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
430
Enrico Granata56768392013-04-23 20:05:05 +0000431 size_t data_read = 0;
432 if (needs_zero_terminator)
433 data_read = process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
434 else
435 data_read = process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
436
Enrico Granata93d59662013-01-14 23:53:26 +0000437 if (error.Fail() || data_read == 0)
438 {
Enrico Granata56768392013-04-23 20:05:05 +0000439 options.GetStream()->Printf("unable to read data");
Enrico Granataf68df122013-01-10 22:08:35 +0000440 return true;
441 }
Enrico Granata93d59662013-01-14 23:53:26 +0000442
443 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
444
Enrico Granata56768392013-04-23 20:05:05 +0000445 return DumpUTFBufferToStream(options.GetConversionFunction(), data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize);
Enrico Granataf68df122013-01-10 22:08:35 +0000446}
447
448bool
449lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
450{
451 ProcessSP process_sp = valobj.GetProcessSP();
452 if (!process_sp)
453 return false;
454
455 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
456
457 if (!valobj_addr)
458 return false;
459
Enrico Granata56768392013-04-23 20:05:05 +0000460 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
461 options.SetLocation(valobj_addr);
462 options.SetConversionFunction(ConvertUTF16toUTF8);
463 options.SetProcessSP(process_sp);
464 options.SetStream(&stream);
465 options.SetPrefixToken('u');
466
467 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000468 {
469 stream.Printf("Summary Unavailable");
470 return true;
471 }
472
473 return true;
474}
475
476bool
477lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
478{
479 ProcessSP process_sp = valobj.GetProcessSP();
480 if (!process_sp)
481 return false;
482
483 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
484
485 if (!valobj_addr)
486 return false;
487
Enrico Granata56768392013-04-23 20:05:05 +0000488 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
489 options.SetLocation(valobj_addr);
490 options.SetConversionFunction(ConvertUTF32toUTF8);
491 options.SetProcessSP(process_sp);
492 options.SetStream(&stream);
Enrico Granatac03c5862013-04-23 21:37:33 +0000493 options.SetPrefixToken('U');
Enrico Granata56768392013-04-23 20:05:05 +0000494
495 if (!ReadUTFBufferAndDumpToStream(options))
Enrico Granataf68df122013-01-10 22:08:35 +0000496 {
497 stream.Printf("Summary Unavailable");
498 return true;
499 }
500
501 return true;
502}
503
504bool
505lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
506{
Enrico Granata38352042013-01-11 02:44:00 +0000507 ProcessSP process_sp = valobj.GetProcessSP();
508 if (!process_sp)
509 return false;
510
Enrico Granata3309d882013-01-12 01:00:22 +0000511 lldb::addr_t data_addr = 0;
512
513 if (valobj.IsPointerType())
514 data_addr = valobj.GetValueAsUnsigned(0);
515 else if (valobj.IsArrayType())
516 data_addr = valobj.GetAddressOf();
Enrico Granata38352042013-01-11 02:44:00 +0000517
Enrico Granata3309d882013-01-12 01:00:22 +0000518 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata38352042013-01-11 02:44:00 +0000519 return false;
520
521 clang::ASTContext* ast = valobj.GetClangAST();
522
523 if (!ast)
524 return false;
525
526 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
527
528 switch (wchar_size)
529 {
530 case 8:
Enrico Granata56768392013-04-23 20:05:05 +0000531 {
Enrico Granata38352042013-01-11 02:44:00 +0000532 // utf 8
Enrico Granata56768392013-04-23 20:05:05 +0000533
534 ReadUTFBufferAndDumpToStreamOptions<UTF8> options;
535 options.SetLocation(data_addr);
536 options.SetConversionFunction(nullptr);
537 options.SetProcessSP(process_sp);
538 options.SetStream(&stream);
539 options.SetPrefixToken('L');
540
541 return ReadUTFBufferAndDumpToStream(options);
542 }
Enrico Granata38352042013-01-11 02:44:00 +0000543 case 16:
Enrico Granata56768392013-04-23 20:05:05 +0000544 {
Enrico Granata38352042013-01-11 02:44:00 +0000545 // utf 16
Enrico Granata56768392013-04-23 20:05:05 +0000546 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
547 options.SetLocation(data_addr);
548 options.SetConversionFunction(ConvertUTF16toUTF8);
549 options.SetProcessSP(process_sp);
550 options.SetStream(&stream);
551 options.SetPrefixToken('L');
552
553 return ReadUTFBufferAndDumpToStream(options);
554 }
Enrico Granata38352042013-01-11 02:44:00 +0000555 case 32:
Enrico Granata56768392013-04-23 20:05:05 +0000556 {
Enrico Granata38352042013-01-11 02:44:00 +0000557 // utf 32
Enrico Granata56768392013-04-23 20:05:05 +0000558 ReadUTFBufferAndDumpToStreamOptions<UTF32> options;
559 options.SetLocation(data_addr);
560 options.SetConversionFunction(ConvertUTF32toUTF8);
561 options.SetProcessSP(process_sp);
562 options.SetStream(&stream);
563 options.SetPrefixToken('L');
564
565 return ReadUTFBufferAndDumpToStream(options);
566 }
Enrico Granata93d59662013-01-14 23:53:26 +0000567 default:
568 stream.Printf("size for wchar_t is not valid");
569 return true;
570 }
571 return true;
572}
573
574bool
575lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
576{
577 DataExtractor data;
578 valobj.GetData(data);
579
580 std::string value;
581 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
582 if (!value.empty())
583 stream.Printf("%s ", value.c_str());
584
585 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
586}
587
588bool
589lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
590{
591 DataExtractor data;
592 valobj.GetData(data);
593
594 std::string value;
595 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
596 if (!value.empty())
597 stream.Printf("%s ", value.c_str());
598
599 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
600}
601
602bool
603lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
604{
605 DataExtractor data;
606 valobj.GetData(data);
607
608 clang::ASTContext* ast = valobj.GetClangAST();
609
610 if (!ast)
611 return false;
612
613 std::string value;
614
615 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
616
617 switch (wchar_size)
618 {
619 case 8:
620 // utf 8
621 valobj.GetValueAsCString(lldb::eFormatChar, value);
622 if (!value.empty())
623 stream.Printf("%s ", value.c_str());
624 return DumpUTFBufferToStream<UTF8>(nullptr,
625 data,
626 stream,
627 'L',
628 '\'',
629 1);
630 case 16:
631 // utf 16
632 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
633 if (!value.empty())
634 stream.Printf("%s ", value.c_str());
635 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
636 data,
637 stream,
638 'L',
639 '\'',
640 1);
641 case 32:
642 // utf 32
643 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
644 if (!value.empty())
645 stream.Printf("%s ", value.c_str());
646 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
647 data,
648 stream,
649 'L',
650 '\'',
651 1);
Enrico Granata38352042013-01-11 02:44:00 +0000652 default:
653 stream.Printf("size for wchar_t is not valid");
654 return true;
655 }
656 return true;
Enrico Granataf68df122013-01-10 22:08:35 +0000657}
658
Enrico Granataa3962a72013-05-15 00:47:46 +0000659// the field layout in a libc++ string (cap, side, data or data, size, cap)
660enum LibcxxStringLayoutMode
661{
662 eLibcxxStringLayoutModeCSD = 0,
663 eLibcxxStringLayoutModeDSC = 1,
664 eLibcxxStringLayoutModeInvalid = 0xffff
665};
666
667// this function abstracts away the layout and mode details of a libc++ string
668// and returns the address of the data and the size ready for callers to consume
Enrico Granata3309d882013-01-12 01:00:22 +0000669static bool
670ExtractLibcxxStringInfo (ValueObject& valobj,
671 ValueObjectSP &location_sp,
672 uint64_t& size)
673{
674 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
675 if (!D)
676 return false;
677
Enrico Granataa3962a72013-05-15 00:47:46 +0000678 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
679
680 // this child should exist
681 if (!layout_decider)
Enrico Granata3309d882013-01-12 01:00:22 +0000682 return false;
683
Enrico Granataa3962a72013-05-15 00:47:46 +0000684 ConstString g_data_name("__data_");
685 ConstString g_size_name("__size_");
686 bool short_mode = false; // this means the string is in short-mode and the data is stored inline
687 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
688 uint64_t size_mode_value = 0;
Enrico Granata3309d882013-01-12 01:00:22 +0000689
Enrico Granataa3962a72013-05-15 00:47:46 +0000690 if (layout == eLibcxxStringLayoutModeDSC)
691 {
692 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
693 if (!size_mode)
694 return false;
695
696 if (size_mode->GetName() != g_size_name)
697 {
698 // we are hitting the padding structure, move along
699 size_mode = D->GetChildAtIndexPath({1,1,1});
700 if (!size_mode)
701 return false;
702 }
703
704 size_mode_value = (size_mode->GetValueAsUnsigned(0));
705 short_mode = ((size_mode_value & 0x80) == 0);
706 }
707 else
708 {
709 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
710 if (!size_mode)
711 return false;
712
713 size_mode_value = (size_mode->GetValueAsUnsigned(0));
714 short_mode = ((size_mode_value & 1) == 0);
715 }
716
717 if (short_mode)
Enrico Granata3309d882013-01-12 01:00:22 +0000718 {
719 ValueObjectSP s(D->GetChildAtIndex(1, true));
720 if (!s)
721 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000722 location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
723 size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
Enrico Granata3309d882013-01-12 01:00:22 +0000724 return (location_sp.get() != nullptr);
725 }
726 else
727 {
728 ValueObjectSP l(D->GetChildAtIndex(0, true));
729 if (!l)
730 return false;
Enrico Granataa3962a72013-05-15 00:47:46 +0000731 // we can use the layout_decider object as the data pointer
732 location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
Enrico Granata3309d882013-01-12 01:00:22 +0000733 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
734 if (!size_vo || !location_sp)
735 return false;
736 size = size_vo->GetValueAsUnsigned(0);
737 return true;
738 }
739}
740
741bool
742lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
743{
744 uint64_t size = 0;
745 ValueObjectSP location_sp((ValueObject*)nullptr);
746 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
747 return false;
748 if (size == 0)
749 {
750 stream.Printf("L\"\"");
751 return true;
Enrico Granataa3962a72013-05-15 00:47:46 +0000752 }
Enrico Granata3309d882013-01-12 01:00:22 +0000753 if (!location_sp)
754 return false;
755 return WCharStringSummaryProvider(*location_sp.get(), stream);
756}
757
758bool
759lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
760{
761 uint64_t size = 0;
762 ValueObjectSP location_sp((ValueObject*)nullptr);
763 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
764 return false;
765 if (size == 0)
766 {
767 stream.Printf("\"\"");
768 return true;
769 }
770 if (!location_sp)
771 return false;
772 Error error;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000773 if (location_sp->ReadPointedString(stream,
774 error,
775 0, // max length is decided by the settings
776 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
777 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granata3309d882013-01-12 01:00:22 +0000778 return error.Success();
779}
780
Enrico Granata55900862013-03-15 18:55:30 +0000781bool
782lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
783{
784 ProcessSP process_sp = valobj.GetProcessSP();
785 if (!process_sp)
786 return false;
787
788 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
789
790 if (!runtime)
791 return false;
792
Greg Clayton03da4cc2013-04-19 21:31:16 +0000793 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata55900862013-03-15 18:55:30 +0000794
795 if (!descriptor.get() || !descriptor->IsValid())
796 return false;
797
798 const char* class_name = descriptor->GetClassName().GetCString();
799
800 if (!class_name || !*class_name)
801 return false;
802
803 stream.Printf("%s",class_name);
804 return true;
805}
806
Enrico Granatac76b97b2013-04-26 00:59:02 +0000807class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
808{
809public:
810 ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
811 SyntheticChildrenFrontEnd(*valobj_sp.get())
812 {
813 }
814
815 virtual size_t
816 CalculateNumChildren ()
817 {
818 return 0;
819 }
820
821 virtual lldb::ValueObjectSP
822 GetChildAtIndex (size_t idx)
823 {
824 return lldb::ValueObjectSP();
825 }
826
827 virtual bool
828 Update()
829 {
830 return false;
831 }
832
833 virtual bool
834 MightHaveChildren ()
835 {
836 return false;
837 }
838
839 virtual size_t
840 GetIndexOfChildWithName (const ConstString &name)
841 {
842 return UINT32_MAX;
843 }
844
845 virtual
846 ~ObjCClassSyntheticChildrenFrontEnd ()
847 {
848 }
849};
850
851SyntheticChildrenFrontEnd*
852lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
853{
854 return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
855}
856
Enrico Granataf5196282012-09-04 18:48:21 +0000857template<bool needs_at>
858bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000859lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000860{
861 ProcessSP process_sp = valobj.GetProcessSP();
862 if (!process_sp)
863 return false;
864
865 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
866
867 if (!runtime)
868 return false;
869
870 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
871
872 if (!descriptor.get() || !descriptor->IsValid())
873 return false;
874
875 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
876 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
877
878 if (!valobj_addr)
879 return false;
880
881 uint64_t value = 0;
882
883 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata6d390772012-09-29 00:47:43 +0000884
885 if (!class_name || !*class_name)
886 return false;
887
Enrico Granataf5196282012-09-04 18:48:21 +0000888 if (!strcmp(class_name,"NSConcreteData") ||
889 !strcmp(class_name,"NSConcreteMutableData") ||
890 !strcmp(class_name,"__NSCFData"))
891 {
892 uint32_t offset = (is_64bit ? 16 : 8);
893 Error error;
894 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
895 if (error.Fail())
896 return false;
897 }
898 else
899 {
Enrico Granatab2698cd2012-09-13 18:27:09 +0000900 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granataf5196282012-09-04 18:48:21 +0000901 return false;
902 }
903
Daniel Malead01b2952012-11-29 21:49:15 +0000904 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granataf5196282012-09-04 18:48:21 +0000905 (needs_at ? "@\"" : ""),
906 value,
Enrico Granata1c333d02013-05-31 01:14:22 +0000907 (value != 1 ? "s" : ""),
Enrico Granataf5196282012-09-04 18:48:21 +0000908 (needs_at ? "\"" : ""));
909
910 return true;
911}
912
Enrico Granata87f00b42013-02-21 20:31:18 +0000913static bool
914ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
915 lldb::ProcessSP& process_sp,
916 Stream& dest,
Enrico Granatad83bfce2013-04-02 21:25:34 +0000917 uint32_t size = 0,
Enrico Granata87f00b42013-02-21 20:31:18 +0000918 Error* error = NULL,
919 size_t *data_read = NULL,
920 char prefix_token = '@',
921 char quote = '"')
922{
923 Error my_error;
924 size_t my_data_read;
925 if (!process_sp || location == 0)
926 return false;
927
Enrico Granata23ab35a2013-04-02 23:07:55 +0000928 if (!size)
929 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
930 else
931 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata87f00b42013-02-21 20:31:18 +0000932
933 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
934
935 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
936
937 if (error)
938 *error = my_error;
939 if (data_read)
940 *data_read = my_data_read;
941
942 if (my_error.Fail())
943 return false;
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000944
945 dest.Printf("%c%c",prefix_token,quote);
946
Enrico Granata87f00b42013-02-21 20:31:18 +0000947 if (my_data_read)
Enrico Granata5a9c4fe2013-05-17 23:28:13 +0000948 dest.Printf("%s",(char*)buffer_sp->GetBytes());
949
950 dest.Printf("%c",quote);
Enrico Granata87f00b42013-02-21 20:31:18 +0000951
952 return true;
953}
954
Enrico Granatad83bfce2013-04-02 21:25:34 +0000955#ifdef WANT_DEEP_PRINT
956struct lldb__notInlineMutable {
957 void *buffer;
958 signed long length;
959 signed long capacity;
960 unsigned int hasGap:1;
961 unsigned int isFixedCapacity:1;
962 unsigned int isExternalMutable:1;
963 unsigned int capacityProvidedExternally:1;
964#if __LP64__
965 unsigned long desiredCapacity:60;
966#else
967 unsigned long desiredCapacity:28;
968#endif
969 void* contentsAllocator;
970};
971
972struct lldb__CFString {
973 uintptr_t _cfisa;
974 uint8_t _cfinfo[4];
975 uint32_t _rc;
976 union {
977 struct __inline1 {
978 signed long length;
979 } inline1;
980 struct __notInlineImmutable1 {
981 void *buffer;
982 signed long length;
983 void* contentsDeallocator;
984 } notInlineImmutable1;
985 struct __notInlineImmutable2 {
986 void *buffer;
987 void* contentsDeallocator;
988 } notInlineImmutable2;
989 struct lldb__notInlineMutable notInlineMutable;
990 } variants;
991};
992#endif
993
Enrico Granataf5196282012-09-04 18:48:21 +0000994bool
Enrico Granatab2698cd2012-09-13 18:27:09 +0000995lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granataf5196282012-09-04 18:48:21 +0000996{
997 ProcessSP process_sp = valobj.GetProcessSP();
998 if (!process_sp)
999 return false;
1000
1001 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1002
1003 if (!runtime)
1004 return false;
1005
1006 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
1007
1008 if (!descriptor.get() || !descriptor->IsValid())
1009 return false;
1010
1011 uint32_t ptr_size = process_sp->GetAddressByteSize();
1012
1013 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1014
1015 if (!valobj_addr)
1016 return false;
1017
1018 const char* class_name = descriptor->GetClassName().GetCString();
1019
Enrico Granata60b81df2012-09-29 00:45:53 +00001020 if (!class_name || !*class_name)
1021 return false;
1022
Enrico Granataf5196282012-09-04 18:48:21 +00001023 uint64_t info_bits_location = valobj_addr + ptr_size;
1024 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
1025 info_bits_location += 3;
1026
Enrico Granata87f00b42013-02-21 20:31:18 +00001027 Error error;
Enrico Granataf5196282012-09-04 18:48:21 +00001028
1029 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
1030 if (error.Fail())
1031 return false;
1032
1033 bool is_mutable = (info_bits & 1) == 1;
1034 bool is_inline = (info_bits & 0x60) == 0;
1035 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
1036 bool is_unicode = (info_bits & 0x10) == 0x10;
1037 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001038 bool has_null = (info_bits & 8) == 8;
1039
1040 size_t explicit_length = 0;
1041 if (!has_null && has_explicit_length && !is_special)
1042 {
1043 lldb::addr_t explicit_length_offset = 2*ptr_size;
1044 if (is_mutable and not is_inline)
1045 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
1046 else if (is_inline)
1047 explicit_length = explicit_length + 0; // inline1.length;
1048 else if (not is_inline and not is_mutable)
1049 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
1050 else
1051 explicit_length_offset = 0;
1052
1053 if (explicit_length_offset)
1054 {
1055 explicit_length_offset = valobj_addr + explicit_length_offset;
1056 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
1057 }
1058 }
1059
1060#ifdef WANT_DEEP_PRINT
1061 lldb__CFString my_string_data;
1062 process_sp->ReadMemory(valobj_addr, &my_string_data, sizeof(lldb__CFString),error);
1063
1064 printf(R"(
1065 __CFString my_string_data = {
1066 uintptr_t _cfisa = %lu
1067 uint8_t _cfinfo[4] = %c%c%c%c
1068 uint32_t _rc = %d
1069 union {
1070 struct __inline1 {
1071 signed long length = %ld
1072 } inline1;
1073 struct __notInlineImmutable1 {
1074 void *buffer = %p
1075 signed long length = %ld
1076 void* contentsDeallocator = %p
1077 } notInlineImmutable1;
1078 struct __notInlineImmutable2 {
1079 void *buffer = %p
1080 void* contentsDeallocator = %p
1081 } notInlineImmutable2;
1082 struct __notInlineMutable notInlineMutable {
1083 void *buffer = %p
1084 signed long length = %ld
1085 signed long capacity = %ld
1086 unsigned int hasGap:1 = %d
1087 unsigned int isFixedCapacity:1 = %d
1088 unsigned int isExternalMutable:1 = %d
1089 unsigned int capacityProvidedExternally:1 = %d
1090#if __LP64__
1091 unsigned long desiredCapacity:60 = %lu
1092#else
1093 unsigned long desiredCapacity:28 = %lu
1094#endif
1095 void* contentsAllocator = %p
1096 }
Enrico Granata56768392013-04-23 20:05:05 +00001097 } variants; ==> (M:%dI:%dL:%zuU:%dS:%dN:%d)
Enrico Granatad83bfce2013-04-02 21:25:34 +00001098 };\n)",
1099 my_string_data._cfisa,
1100 my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
1101 my_string_data._rc,
1102 my_string_data.variants.inline1.length,
1103 my_string_data.variants.notInlineImmutable1.buffer,
1104 my_string_data.variants.notInlineImmutable1.length,
1105 my_string_data.variants.notInlineImmutable1.contentsDeallocator,
1106 my_string_data.variants.notInlineImmutable2.buffer,
1107 my_string_data.variants.notInlineImmutable2.contentsDeallocator,
1108 my_string_data.variants.notInlineMutable.buffer,
1109 my_string_data.variants.notInlineMutable.length,
1110 my_string_data.variants.notInlineMutable.capacity,
1111 my_string_data.variants.notInlineMutable.hasGap,
1112 my_string_data.variants.notInlineMutable.isFixedCapacity,
1113 my_string_data.variants.notInlineMutable.isExternalMutable,
1114 my_string_data.variants.notInlineMutable.capacityProvidedExternally,
1115 my_string_data.variants.notInlineMutable.desiredCapacity,
1116 my_string_data.variants.notInlineMutable.desiredCapacity,
Enrico Granata56768392013-04-23 20:05:05 +00001117 my_string_data.variants.notInlineMutable.contentsAllocator,
1118 is_mutable,
1119 is_inline,
1120 explicit_length,
1121 is_unicode,
1122 is_special,
1123 has_null);
Enrico Granatad83bfce2013-04-02 21:25:34 +00001124#endif
Enrico Granataf5196282012-09-04 18:48:21 +00001125
1126 if (strcmp(class_name,"NSString") &&
1127 strcmp(class_name,"CFStringRef") &&
1128 strcmp(class_name,"CFMutableStringRef") &&
1129 strcmp(class_name,"__NSCFConstantString") &&
1130 strcmp(class_name,"__NSCFString") &&
1131 strcmp(class_name,"NSCFConstantString") &&
1132 strcmp(class_name,"NSCFString") &&
1133 strcmp(class_name,"NSPathStore2"))
1134 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001135 // not one of us - but tell me class name
1136 stream.Printf("class name = %s",class_name);
1137 return true;
Enrico Granataf5196282012-09-04 18:48:21 +00001138 }
1139
1140 if (is_mutable)
1141 {
1142 uint64_t location = 2 * ptr_size + valobj_addr;
1143 location = process_sp->ReadPointerFromMemory(location, error);
1144 if (error.Fail())
1145 return false;
1146 if (has_explicit_length and is_unicode)
Enrico Granata56768392013-04-23 20:05:05 +00001147 {
1148 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1149 options.SetConversionFunction(ConvertUTF16toUTF8);
1150 options.SetLocation(location);
1151 options.SetProcessSP(process_sp);
1152 options.SetStream(&stream);
1153 options.SetPrefixToken('@');
1154 options.SetQuote('"');
1155 options.SetSourceSize(explicit_length);
1156 options.SetNeedsZeroTermination(false);
1157 return ReadUTFBufferAndDumpToStream (options);
1158 }
Enrico Granataf5196282012-09-04 18:48:21 +00001159 else
Enrico Granatad83bfce2013-04-02 21:25:34 +00001160 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001161 }
1162 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
1163 {
1164 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001165 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001166 }
1167 else if (is_unicode)
1168 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001169 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001170 if (is_inline)
1171 {
1172 if (!has_explicit_length)
1173 {
1174 stream.Printf("found new combo");
1175 return true;
1176 }
1177 else
1178 location += ptr_size;
Enrico Granata56768392013-04-23 20:05:05 +00001179 }
Enrico Granataf5196282012-09-04 18:48:21 +00001180 else
1181 {
1182 location = process_sp->ReadPointerFromMemory(location, error);
1183 if (error.Fail())
1184 return false;
1185 }
Enrico Granata56768392013-04-23 20:05:05 +00001186 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1187 options.SetConversionFunction(ConvertUTF16toUTF8);
1188 options.SetLocation(location);
1189 options.SetProcessSP(process_sp);
1190 options.SetStream(&stream);
1191 options.SetPrefixToken('@');
1192 options.SetQuote('"');
1193 options.SetSourceSize(explicit_length);
1194 options.SetNeedsZeroTermination(has_explicit_length == false);
1195 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001196 }
1197 else if (is_special)
1198 {
1199 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granata56768392013-04-23 20:05:05 +00001200 ReadUTFBufferAndDumpToStreamOptions<UTF16> options;
1201 options.SetConversionFunction(ConvertUTF16toUTF8);
1202 options.SetLocation(location);
1203 options.SetProcessSP(process_sp);
1204 options.SetStream(&stream);
1205 options.SetPrefixToken('@');
1206 options.SetQuote('"');
1207 options.SetSourceSize(explicit_length);
1208 options.SetNeedsZeroTermination(has_explicit_length == false);
1209 return ReadUTFBufferAndDumpToStream (options);
Enrico Granataf5196282012-09-04 18:48:21 +00001210 }
1211 else if (is_inline)
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 if (!has_explicit_length)
1215 location++;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001216 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001217 }
1218 else
1219 {
Enrico Granata87f00b42013-02-21 20:31:18 +00001220 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granataf5196282012-09-04 18:48:21 +00001221 location = process_sp->ReadPointerFromMemory(location, error);
1222 if (error.Fail())
1223 return false;
Enrico Granatad83bfce2013-04-02 21:25:34 +00001224 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granataf5196282012-09-04 18:48:21 +00001225 }
1226
1227 stream.Printf("class name = %s",class_name);
1228 return true;
1229
1230}
1231
Enrico Granataf175ad12012-10-03 23:53:45 +00001232bool
Enrico Granata5bfce362013-02-08 01:55:46 +00001233lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1234{
1235 TargetSP target_sp(valobj.GetTargetSP());
1236 if (!target_sp)
1237 return false;
1238 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
1239 uint64_t pointee = valobj.GetValueAsUnsigned(0);
1240 if (!pointee)
1241 return false;
1242 pointee += addr_size;
1243 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
1244 ExecutionContext exe_ctx(target_sp,false);
1245 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
1246 if (!child_ptr_sp)
1247 return false;
1248 DataExtractor data;
1249 child_ptr_sp->GetData(data);
1250 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
1251 child_sp->GetValueAsUnsigned(0);
1252 if (child_sp)
1253 return NSStringSummaryProvider(*child_sp, stream);
1254 return false;
1255}
1256
1257bool
1258lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
1259{
1260 return NSAttributedStringSummaryProvider(valobj, stream);
1261}
1262
1263bool
Enrico Granataf175ad12012-10-03 23:53:45 +00001264lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
1265{
1266 stream.Printf("%s",valobj.GetObjectDescription());
1267 return true;
1268}
1269
Enrico Granatab5887262012-10-29 21:18:03 +00001270bool
1271lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
1272{
1273 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
1274 valobj.GetClangAST(),
1275 NULL);
1276
1277 ValueObjectSP real_guy_sp = valobj.GetSP();
1278
1279 if (type_info & ClangASTContext::eTypeIsPointer)
1280 {
1281 Error err;
1282 real_guy_sp = valobj.Dereference(err);
1283 if (err.Fail() || !real_guy_sp)
1284 return false;
1285 }
1286 else if (type_info & ClangASTContext::eTypeIsReference)
1287 {
1288 real_guy_sp = valobj.GetChildAtIndex(0, true);
1289 if (!real_guy_sp)
1290 return false;
1291 }
1292 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
1293 if (value == 0)
1294 {
1295 stream.Printf("NO");
1296 return true;
1297 }
1298 stream.Printf("YES");
1299 return true;
1300}
1301
1302template <bool is_sel_ptr>
1303bool
1304lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1305{
Enrico Granata75dfb432013-02-15 00:06:04 +00001306 lldb::ValueObjectSP valobj_sp;
Enrico Granatab5887262012-10-29 21:18:03 +00001307
Enrico Granata75dfb432013-02-15 00:06:04 +00001308 if (!valobj.GetClangAST())
Enrico Granatab5887262012-10-29 21:18:03 +00001309 return false;
Enrico Granata75dfb432013-02-15 00:06:04 +00001310 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1311 if (!char_opaque_type)
1312 return false;
1313 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1314
Enrico Granatab5887262012-10-29 21:18:03 +00001315 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1316
Enrico Granata75dfb432013-02-15 00:06:04 +00001317 if (is_sel_ptr)
1318 {
1319 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1320 if (data_address == LLDB_INVALID_ADDRESS)
1321 return false;
1322 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1323 }
1324 else
1325 {
1326 DataExtractor data;
1327 valobj.GetData(data);
1328 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1329 }
Enrico Granatab5887262012-10-29 21:18:03 +00001330
Enrico Granata75dfb432013-02-15 00:06:04 +00001331 if (!valobj_sp)
1332 return false;
Enrico Granatab5887262012-10-29 21:18:03 +00001333
1334 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1335 return true;
1336}
1337
Enrico Granata6d37cc62013-03-19 00:27:22 +00001338// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1339// this call gives the POSIX equivalent of the Cocoa epoch
1340time_t
Enrico Granata92373532013-03-19 22:58:48 +00001341lldb_private::formatters::GetOSXEpoch ()
Enrico Granata6d37cc62013-03-19 00:27:22 +00001342{
1343 static time_t epoch = 0;
1344 if (!epoch)
1345 {
1346 tzset();
1347 tm tm_epoch;
1348 tm_epoch.tm_sec = 0;
1349 tm_epoch.tm_hour = 0;
1350 tm_epoch.tm_min = 0;
1351 tm_epoch.tm_mon = 0;
1352 tm_epoch.tm_mday = 1;
1353 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1354 tm_epoch.tm_isdst = -1;
1355 tm_epoch.tm_gmtoff = 0;
1356 tm_epoch.tm_zone = NULL;
1357 epoch = timegm(&tm_epoch);
1358 }
1359 return epoch;
1360}
1361
Greg Claytonc7bece562013-01-25 18:06:21 +00001362size_t
Enrico Granataf615b802013-02-15 23:38:37 +00001363lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001364{
1365 if (!item_name || !*item_name)
1366 return UINT32_MAX;
1367 if (*item_name != '[')
1368 return UINT32_MAX;
1369 item_name++;
Enrico Granataf615b802013-02-15 23:38:37 +00001370 char* endptr = NULL;
1371 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1372 if (idx == 0 && endptr == item_name)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001373 return UINT32_MAX;
Enrico Granataf615b802013-02-15 23:38:37 +00001374 if (idx == ULONG_MAX)
Enrico Granatab2698cd2012-09-13 18:27:09 +00001375 return UINT32_MAX;
1376 return idx;
1377}
1378
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001379lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1380 ConstString item_name) :
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001381SyntheticChildrenFrontEnd(*valobj_sp.get()),
1382m_exe_ctx_ref(),
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001383m_item_name(item_name),
1384m_item_sp()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001385{
1386 if (valobj_sp)
1387 Update();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001388}
1389
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001390bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001391lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001392{
Enrico Granata6eca3552013-03-28 18:50:54 +00001393 m_item_sp.reset();
1394
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001395 ValueObjectSP valobj_sp = m_backend.GetSP();
1396 if (!valobj_sp)
1397 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001398
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001399 if (!valobj_sp)
1400 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001401
1402 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1403 if (!item_ptr)
1404 return false;
1405 if (item_ptr->GetValueAsUnsigned(0) == 0)
1406 return false;
1407 Error err;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001408 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001409 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
1410 if (err.Fail())
1411 m_item_sp.reset();
Enrico Granata6eca3552013-03-28 18:50:54 +00001412 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001413}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001414
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001415size_t
1416lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1417{
1418 return 1;
1419}
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001420
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001421lldb::ValueObjectSP
1422lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1423{
1424 if (idx == 0)
1425 return m_item_sp;
1426 return lldb::ValueObjectSP();
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001427}
1428
1429bool
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001430lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001431{
1432 return true;
1433}
1434
1435size_t
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001436lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001437{
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001438 if (name == ConstString("item"))
1439 return 0;
1440 return UINT32_MAX;
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001441}
1442
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001443lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001444{
Enrico Granata3b1b2da2013-02-04 22:54:42 +00001445}
1446
Enrico Granataf5196282012-09-04 18:48:21 +00001447template bool
Enrico Granatab2698cd2012-09-13 18:27:09 +00001448lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1449
1450template bool
1451lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatab5887262012-10-29 21:18:03 +00001452
1453template bool
1454lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1455
1456template bool
1457lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;