LLDB mainline
Cocoa.cpp
Go to the documentation of this file.
1//===-- Cocoa.cpp ---------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Cocoa.h"
10#include "NSString.h"
11#include "ObjCConstants.h"
12
15#include "lldb/Core/Mangled.h"
19#include "lldb/Host/Time.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/Target.h"
24#include "lldb/Utility/Endian.h"
26#include "lldb/Utility/Status.h"
27#include "lldb/Utility/Stream.h"
30
31#include "llvm/ADT/APInt.h"
32#include "llvm/ADT/bit.h"
33
34using namespace lldb;
35using namespace lldb_private;
36using namespace lldb_private::formatters;
37
39 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
40 ProcessSP process_sp = valobj.GetProcessSP();
41 if (!process_sp)
42 return false;
43
44 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
45
46 if (!runtime)
47 return false;
48
50 runtime->GetClassDescriptor(valobj));
51
52 if (!descriptor || !descriptor->IsValid())
53 return false;
54
55 uint32_t ptr_size = process_sp->GetAddressByteSize();
56
57 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
58
59 if (!valobj_addr)
60 return false;
61
62 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
63
64 if (class_name.empty())
65 return false;
66
67 if (class_name == "NSBundle") {
68 uint64_t offset = 5 * ptr_size;
70 offset,
72 true));
73
74 if (!text)
75 return false;
76
77 StreamString summary_stream;
78 bool was_nsstring_ok =
79 NSStringSummaryProvider(*text, summary_stream, options);
80 if (was_nsstring_ok && summary_stream.GetSize() > 0) {
81 stream.Printf("%s", summary_stream.GetData());
82 return true;
83 }
84 }
85
86 return false;
87}
88
90 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
91 ProcessSP process_sp = valobj.GetProcessSP();
92 if (!process_sp)
93 return false;
94
95 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
96
97 if (!runtime)
98 return false;
99
101 runtime->GetClassDescriptor(valobj));
102
103 if (!descriptor || !descriptor->IsValid())
104 return false;
105
106 uint32_t ptr_size = process_sp->GetAddressByteSize();
107
108 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
109
110 if (!valobj_addr)
111 return false;
112
113 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
114
115 if (class_name.empty())
116 return false;
117
118 if (class_name == "__NSTimeZone") {
119 uint64_t offset = ptr_size;
121 offset, valobj.GetCompilerType(), true));
122
123 if (!text)
124 return false;
125
126 StreamString summary_stream;
127 bool was_nsstring_ok =
128 NSStringSummaryProvider(*text, summary_stream, options);
129 if (was_nsstring_ok && summary_stream.GetSize() > 0) {
130 stream.Printf("%s", summary_stream.GetData());
131 return true;
132 }
133 }
134
135 return false;
136}
137
139 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
140 ProcessSP process_sp = valobj.GetProcessSP();
141 if (!process_sp)
142 return false;
143
144 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
145
146 if (!runtime)
147 return false;
148
150 runtime->GetClassDescriptor(valobj));
151
152 if (!descriptor || !descriptor->IsValid())
153 return false;
154
155 uint32_t ptr_size = process_sp->GetAddressByteSize();
156
157 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
158
159 if (!valobj_addr)
160 return false;
161
162 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
163
164 if (class_name.empty())
165 return false;
166
167 if (class_name == "NSConcreteNotification") {
168 uint64_t offset = ptr_size;
170 offset, valobj.GetCompilerType(), true));
171
172 if (!text)
173 return false;
174
175 StreamString summary_stream;
176 bool was_nsstring_ok =
177 NSStringSummaryProvider(*text, summary_stream, options);
178 if (was_nsstring_ok && summary_stream.GetSize() > 0) {
179 stream.Printf("%s", summary_stream.GetData());
180 return true;
181 }
182 }
183
184 return false;
185}
186
188 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
189 ProcessSP process_sp = valobj.GetProcessSP();
190 if (!process_sp)
191 return false;
192
193 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
194
195 if (!runtime)
196 return false;
197
199 runtime->GetClassDescriptor(valobj));
200
201 if (!descriptor || !descriptor->IsValid())
202 return false;
203
204 uint32_t ptr_size = process_sp->GetAddressByteSize();
205
206 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
207
208 if (!valobj_addr)
209 return false;
210
211 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
212
213 if (class_name.empty())
214 return false;
215
216 uint64_t port_number = 0;
217
218 if (class_name == "NSMachPort") {
219 uint64_t offset = (ptr_size == 4 ? 12 : 20);
221 port_number = process_sp->ReadUnsignedIntegerFromMemory(
222 offset + valobj_addr, 4, 0, error);
223 if (error.Success()) {
224 stream.Printf("mach port: %u",
225 (uint32_t)(port_number & 0x00000000FFFFFFFF));
226 return true;
227 }
228 }
229
230 return false;
231}
232
234 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
235 ProcessSP process_sp = valobj.GetProcessSP();
236 if (!process_sp)
237 return false;
238
239 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
240 ObjCLanguageRuntime::Get(*process_sp));
241
242 if (!runtime)
243 return false;
244
246 runtime->GetClassDescriptor(valobj));
247
248 if (!descriptor || !descriptor->IsValid())
249 return false;
250
251 uint32_t ptr_size = process_sp->GetAddressByteSize();
252
253 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
254
255 if (!valobj_addr)
256 return false;
257
258 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
259
260 if (class_name.empty())
261 return false;
262
263 uint64_t count = 0;
264
265 do {
266 if (class_name == "NSIndexSet" || class_name == "NSMutableIndexSet") {
267 // Foundation version 2000 added a bitmask if the index set fit in 64 bits
268 // and a Tagged Pointer version if the bitmask is small enough to fit in
269 // the tagged pointer payload.
270 // It also changed the layout (but not the size) of the set descriptor.
271
272 // First check whether this is a tagged pointer. The bitmask will be in
273 // the payload of the tagged pointer.
274 uint64_t payload;
275 if (runtime->GetFoundationVersion() >= 2000 &&
276 descriptor->GetTaggedPointerInfo(nullptr, nullptr, &payload)) {
277 count = llvm::popcount(payload);
278 break;
279 }
280 // The first 32 bits describe the index set in all cases:
282 uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
283 valobj_addr + ptr_size, 4, 0, error);
284 if (error.Fail())
285 return false;
286 // Now check if the index is held in a bitmask in the object:
287 if (runtime->GetFoundationVersion() >= 2000) {
288 // The first two bits are "isSingleRange" and "isBitfield". If this is
289 // a bitfield we handle it here, otherwise set mode appropriately and
290 // the rest of the treatment is in common.
291 if ((mode & 2) == 2) {
292 // The bitfield is a 64 bit uint at the beginning of the data var.
293 uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory(
294 valobj_addr + 2 * ptr_size, 8, 0, error);
295 if (error.Fail())
296 return false;
297 count = llvm::popcount(bitfield);
298 break;
299 }
300 // It wasn't a bitfield, so read the isSingleRange from its new loc:
301 if ((mode & 1) == 1)
302 mode = 1; // this means the set only has one range
303 else
304 mode = 2; // this means the set has multiple ranges
305 } else {
306 // this means the set is empty - count = 0
307 if ((mode & 1) == 1) {
308 count = 0;
309 break;
310 }
311
312 if ((mode & 2) == 2)
313 mode = 1; // this means the set only has one range
314 else
315 mode = 2; // this means the set has multiple ranges
316 }
317 if (mode == 1) {
318 count = process_sp->ReadUnsignedIntegerFromMemory(
319 valobj_addr + 3 * ptr_size, ptr_size, 0, error);
320 if (error.Fail())
321 return false;
322 } else {
323 // read a pointer to the data at 2*ptr_size
324 count = process_sp->ReadUnsignedIntegerFromMemory(
325 valobj_addr + 2 * ptr_size, ptr_size, 0, error);
326 if (error.Fail())
327 return false;
328 // read the data at 2*ptr_size from the first location
329 count = process_sp->ReadUnsignedIntegerFromMemory(count + 2 * ptr_size,
330 ptr_size, 0, error);
331 if (error.Fail())
332 return false;
333 }
334 } else
335 return false;
336 } while (false);
337 stream.Printf("%" PRIu64 " index%s", count, (count == 1 ? "" : "es"));
338 return true;
339}
340
341static void NSNumber_FormatChar(ValueObject &valobj, Stream &stream, char value,
342 lldb::LanguageType lang) {
343 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:char");
344
345 llvm::StringRef prefix, suffix;
346 if (Language *language = Language::FindPlugin(lang))
347 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
348
349 stream << prefix;
350 stream.Printf("%hhd", value);
351 stream << suffix;
352}
353
354static void NSNumber_FormatShort(ValueObject &valobj, Stream &stream,
355 short value, lldb::LanguageType lang) {
356 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:short");
357
358 llvm::StringRef prefix, suffix;
359 if (Language *language = Language::FindPlugin(lang))
360 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
361
362 stream << prefix;
363 stream.Printf("%hd", value);
364 stream << suffix;
365}
366
367static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value,
368 lldb::LanguageType lang) {
369 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:int");
370
371 llvm::StringRef prefix, suffix;
372 if (Language *language = Language::FindPlugin(lang))
373 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
374
375 stream << prefix;
376 stream.Printf("%d", value);
377 stream << suffix;
378}
379
380static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream,
381 int64_t value, lldb::LanguageType lang) {
382 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:long");
383
384 llvm::StringRef prefix, suffix;
385 if (Language *language = Language::FindPlugin(lang))
386 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
387
388 stream << prefix;
389 stream.Printf("%" PRId64 "", value);
390 stream << suffix;
391}
392
393static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream,
394 const llvm::APInt &value,
395 lldb::LanguageType lang) {
396 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:int128_t");
397
398 llvm::StringRef prefix, suffix;
399 if (Language *language = Language::FindPlugin(lang))
400 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
401
402 stream << prefix;
403 const int radix = 10;
404 const bool isSigned = true;
405 std::string str = llvm::toString(value, radix, isSigned);
406 stream.PutCString(str.c_str());
407 stream << suffix;
408}
409
410static void NSNumber_FormatFloat(ValueObject &valobj, Stream &stream,
411 float value, lldb::LanguageType lang) {
412 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:float");
413
414 llvm::StringRef prefix, suffix;
415 if (Language *language = Language::FindPlugin(lang))
416 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
417
418 stream << prefix;
419 stream.Printf("%f", value);
420 stream << suffix;
421}
422
423static void NSNumber_FormatDouble(ValueObject &valobj, Stream &stream,
424 double value, lldb::LanguageType lang) {
425 static constexpr llvm::StringLiteral g_TypeHint("NSNumber:double");
426
427 llvm::StringRef prefix, suffix;
428 if (Language *language = Language::FindPlugin(lang))
429 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
430
431 stream << prefix;
432 stream.Printf("%g", value);
433 stream << suffix;
434}
435
437 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
438 ProcessSP process_sp = valobj.GetProcessSP();
439 if (!process_sp)
440 return false;
441
443 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
444
445 if (!runtime)
446 return false;
447
449 runtime->GetClassDescriptor(valobj));
450
451 if (!descriptor || !descriptor->IsValid())
452 return false;
453
454 uint32_t ptr_size = process_sp->GetAddressByteSize();
455
456 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
457
458 if (!valobj_addr)
459 return false;
460
461 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
462
463 if (class_name.empty())
464 return false;
465
466 if (class_name == "__NSCFBoolean")
467 return ObjCBooleanSummaryProvider(valobj, stream, options);
468
469 if (class_name == "NSDecimalNumber")
470 return NSDecimalNumberSummaryProvider(valobj, stream, options);
471
472 if (class_name == "NSConstantIntegerNumber") {
474 int64_t value = process_sp->ReadSignedIntegerFromMemory(
475 valobj_addr + 2 * ptr_size, 8, 0, error);
476 if (error.Fail())
477 return false;
478 uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory(
479 valobj_addr + ptr_size, ptr_size, 0, error);
480 if (error.Fail())
481 return false;
482 char encoding =
483 process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0, error);
484 if (error.Fail())
485 return false;
486
487 switch (encoding) {
488 case _C_CHR:
489 NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
490 return true;
491 case _C_SHT:
492 NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
493 return true;
494 case _C_INT:
495 NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
496 return true;
497 case _C_LNG:
498 case _C_LNG_LNG:
499 NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
500 return true;
501
502 case _C_UCHR:
503 case _C_USHT:
504 case _C_UINT:
505 case _C_ULNG:
506 case _C_ULNG_LNG:
507 stream.Printf("%" PRIu64, value);
508 return true;
509 }
510
511 return false;
512 }
513
514 if (class_name == "NSConstantFloatNumber") {
516 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
517 valobj_addr + ptr_size, 4, 0, error);
518 if (error.Fail())
519 return false;
520 float flt_value = 0.0f;
521 memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int));
522 NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
523 return true;
524 }
525
526 if (class_name == "NSConstantDoubleNumber") {
528 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
529 valobj_addr + ptr_size, 8, 0, error);
530 if (error.Fail())
531 return false;
532 double dbl_value = 0.0;
533 memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng));
534 NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
535 return true;
536 }
537
538 if (class_name == "NSNumber" || class_name == "__NSCFNumber") {
539 int64_t value = 0;
540 uint64_t i_bits = 0;
541 if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
542 // Check for "preserved" numbers. We still don't support them yet.
543 if (i_bits & 0x8) {
544 if (log)
545 log->Printf(
546 "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
547 valobj_addr);
548 return false;
549 }
550
551 switch (i_bits) {
552 case 0:
553 NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
554 break;
555 case 1:
556 case 4:
557 NSNumber_FormatShort(valobj, stream, (short)value,
558 options.GetLanguage());
559 break;
560 case 2:
561 case 8:
562 NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
563 break;
564 case 3:
565 case 12:
566 NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
567 break;
568 default:
569 return false;
570 }
571 return true;
572 } else {
574
575 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
576 ObjCLanguageRuntime::Get(*process_sp));
577
578 const bool new_format =
579 (runtime && runtime->GetFoundationVersion() >= 1400);
580
581 enum class TypeCodes : int {
582 sint8 = 0x0,
583 sint16 = 0x1,
584 sint32 = 0x2,
585 sint64 = 0x3,
586 f32 = 0x4,
587 f64 = 0x5,
588 sint128 = 0x6
589 };
590
591 uint64_t data_location = valobj_addr + 2 * ptr_size;
592 TypeCodes type_code;
593
594 if (new_format) {
595 uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
596 valobj_addr + ptr_size, ptr_size, 0, error);
597
598 if (error.Fail())
599 return false;
600
601 bool is_preserved_number = cfinfoa & 0x8;
602 if (is_preserved_number) {
603 if (log)
604 log->Printf(
605 "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
606 valobj_addr);
607 return false;
608 }
609
610 type_code = static_cast<TypeCodes>(cfinfoa & 0x7);
611 } else {
612 uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
613 valobj_addr + ptr_size, 1, 0, error) &
614 0x1F;
615
616 if (error.Fail())
617 return false;
618
619 switch (data_type) {
620 case 1:
621 type_code = TypeCodes::sint8;
622 break;
623 case 2:
624 type_code = TypeCodes::sint16;
625 break;
626 case 3:
627 type_code = TypeCodes::sint32;
628 break;
629 case 17:
630 data_location += 8;
631 [[fallthrough]];
632 case 4:
633 type_code = TypeCodes::sint64;
634 break;
635 case 5:
636 type_code = TypeCodes::f32;
637 break;
638 case 6:
639 type_code = TypeCodes::f64;
640 break;
641 default:
642 return false;
643 }
644 }
645
646 uint64_t value = 0;
647 bool success = false;
648 switch (type_code) {
649 case TypeCodes::sint8:
650 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
651 error);
652 if (error.Fail())
653 return false;
654 NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
655 success = true;
656 break;
657 case TypeCodes::sint16:
658 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
659 error);
660 if (error.Fail())
661 return false;
662 NSNumber_FormatShort(valobj, stream, (short)value,
663 options.GetLanguage());
664 success = true;
665 break;
666 case TypeCodes::sint32:
667 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
668 error);
669 if (error.Fail())
670 return false;
671 NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
672 success = true;
673 break;
674 case TypeCodes::sint64:
675 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
676 error);
677 if (error.Fail())
678 return false;
679 NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
680 success = true;
681 break;
682 case TypeCodes::f32: {
683 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
684 data_location, 4, 0, error);
685 if (error.Fail())
686 return false;
687 float flt_value = 0.0f;
688 memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int));
689 NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
690 success = true;
691 break;
692 }
693 case TypeCodes::f64: {
694 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
695 data_location, 8, 0, error);
696 if (error.Fail())
697 return false;
698 double dbl_value = 0.0;
699 memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng));
700 NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
701 success = true;
702 break;
703 }
704 case TypeCodes::sint128: // internally, this is the same
705 {
706 uint64_t words[2];
707 words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
708 0, error);
709 if (error.Fail())
710 return false;
711 words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
712 8, 0, error);
713 if (error.Fail())
714 return false;
715 llvm::APInt i128_value(128, words);
716 NSNumber_FormatInt128(valobj, stream, i128_value,
717 options.GetLanguage());
718 success = true;
719 break;
720 }
721 }
722 return success;
723 }
724 }
725
726 return false;
727}
728
730 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
731 ProcessSP process_sp = valobj.GetProcessSP();
732 if (!process_sp)
733 return false;
734
735 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
736 uint32_t ptr_size = process_sp->GetAddressByteSize();
737
739 int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
740 valobj_addr + ptr_size, 1, 0, error);
741 if (error.Fail())
742 return false;
743
744 uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
745 valobj_addr + ptr_size + 1, 1, 0, error);
746 if (error.Fail())
747 return false;
748
749 // Fifth bit marks negativity.
750 const bool is_negative = (length_and_negative >> 4) & 1;
751
752 // Zero length and negative means NaN.
753 uint8_t length = length_and_negative & 0xf;
754 const bool is_nan = is_negative && (length == 0);
755
756 if (is_nan) {
757 stream.Printf("NaN");
758 return true;
759 }
760
761 if (length == 0) {
762 stream.Printf("0");
763 return true;
764 }
765
766 uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
767 valobj_addr + ptr_size + 4, 8, 0, error);
768 if (error.Fail())
769 return false;
770
771 if (is_negative)
772 stream.Printf("-");
773
774 stream.Printf("%" PRIu64 " x 10^%" PRIi8, mantissa, exponent);
775 return true;
776}
777
779 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
780 ProcessSP process_sp = valobj.GetProcessSP();
781 if (!process_sp)
782 return false;
783
784 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
785
786 if (!runtime)
787 return false;
788
790 runtime->GetClassDescriptor(valobj));
791
792 if (!descriptor || !descriptor->IsValid())
793 return false;
794
795 uint32_t ptr_size = process_sp->GetAddressByteSize();
796
797 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
798
799 if (!valobj_addr)
800 return false;
801
802 llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();
803
804 if (class_name != "NSURL")
805 return false;
806
807 uint64_t offset_text = ptr_size + ptr_size +
808 8; // ISA + pointer + 8 bytes of data (even on 32bit)
809 uint64_t offset_base = offset_text + ptr_size;
810 CompilerType type(valobj.GetCompilerType());
811 ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
812 ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
813 if (!text || text->GetValueAsUnsigned(0) == 0)
814 return false;
815
816 StreamString base_summary;
817 if (base && base->GetValueAsUnsigned(0)) {
818 if (!NSURLSummaryProvider(*base, base_summary, options))
819 base_summary.Clear();
820 }
821 if (base_summary.Empty())
822 return NSStringSummaryProvider(*text, stream, options);
823
824 StreamString summary;
825 if (!NSStringSummaryProvider(*text, summary, options) || summary.Empty())
826 return false;
827
828 static constexpr llvm::StringLiteral quote_char("\"");
829 static constexpr llvm::StringLiteral g_TypeHint("NSString");
830 llvm::StringRef prefix, suffix;
831 if (Language *language = Language::FindPlugin(options.GetLanguage()))
832 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
833
834 // @"A" -> @"A
835 llvm::StringRef summary_str = summary.GetString();
836 bool back_consumed =
837 summary_str.consume_back(suffix) && summary_str.consume_back(quote_char);
838 assert(back_consumed);
839 UNUSED_IF_ASSERT_DISABLED(back_consumed);
840 // @"B" -> B"
841 llvm::StringRef base_summary_str = base_summary.GetString();
842 bool front_consumed = base_summary_str.consume_front(prefix) &&
843 base_summary_str.consume_front(quote_char);
844 assert(front_consumed);
845 UNUSED_IF_ASSERT_DISABLED(front_consumed);
846 // @"A -- B"
847 if (!summary_str.empty() && !base_summary_str.empty()) {
848 stream << summary_str << " -- " << base_summary_str;
849 return true;
850 }
851
852 return false;
853}
854
855/// Bias value for tagged pointer exponents.
856/// Recommended values:
857/// 0x3e3: encodes all dates between distantPast and distantFuture
858/// except for the range within about 1e-28 second of the reference date.
859/// 0x3ef: encodes all dates for a few million years beyond distantPast and
860/// distantFuture, except within about 1e-25 second of the reference date.
862
864 uint64_t fraction : 52; // unsigned
865 uint64_t exponent : 11; // signed
866 uint64_t sign : 1;
867};
868
870 uint64_t fraction : 52; // unsigned
871 uint64_t exponent : 7; // signed
872 uint64_t sign : 1;
873 uint64_t unused : 4; // placeholder for pointer tag bits
874};
875
876static uint64_t decodeExponent(uint64_t exp) {
877 // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits
878 // before performing arithmetic.
879 return llvm::SignExtend64<7>(exp) + TAGGED_DATE_EXPONENT_BIAS;
880}
881
882static double decodeTaggedTimeInterval(uint64_t encodedTimeInterval) {
883 if (encodedTimeInterval == 0)
884 return 0.0;
885 if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
886 return (uint64_t)-0.0;
887
888 TaggedDoubleBits encodedBits =
889 llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval);
890 assert(encodedBits.unused == 0);
891
892 // Sign and fraction are represented exactly.
893 // Exponent is encoded.
894 DoubleBits decodedBits;
895 decodedBits.sign = encodedBits.sign;
896 decodedBits.fraction = encodedBits.fraction;
897 decodedBits.exponent = decodeExponent(encodedBits.exponent);
898
899 return llvm::bit_cast<double>(decodedBits);
900}
901
903 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
904 ProcessSP process_sp = valobj.GetProcessSP();
905 if (!process_sp)
906 return false;
907
908 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
909
910 if (!runtime)
911 return false;
912
914 runtime->GetClassDescriptor(valobj));
915
916 if (!descriptor || !descriptor->IsValid())
917 return false;
918
919 uint32_t ptr_size = process_sp->GetAddressByteSize();
920
921 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
922
923 if (!valobj_addr)
924 return false;
925
926 uint64_t date_value_bits = 0;
927 double date_value = 0.0;
928
929 ConstString class_name = descriptor->GetClassName();
930
931 static const ConstString g_NSDate("NSDate");
932 static const ConstString g_dunder_NSDate("__NSDate");
933 static const ConstString g_NSTaggedDate("__NSTaggedDate");
934 static const ConstString g_NSCalendarDate("NSCalendarDate");
935 static const ConstString g_NSConstantDate("NSConstantDate");
936
937 if (class_name.IsEmpty())
938 return false;
939
940 uint64_t info_bits = 0, value_bits = 0;
941 if ((class_name == g_NSDate) || (class_name == g_dunder_NSDate) ||
942 (class_name == g_NSTaggedDate) || (class_name == g_NSConstantDate)) {
943 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
944 date_value_bits = ((value_bits << 8) | (info_bits << 4));
945 memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
946 } else {
947 llvm::Triple triple(
948 process_sp->GetTarget().GetArchitecture().GetTriple());
949 uint32_t delta =
950 (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size;
952 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
953 valobj_addr + delta, 8, 0, error);
954 memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
955 if (error.Fail())
956 return false;
957 }
958 } else if (class_name == g_NSCalendarDate) {
960 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
961 valobj_addr + 2 * ptr_size, 8, 0, error);
962 memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
963 if (error.Fail())
964 return false;
965 } else
966 return false;
967
968 // FIXME: It seems old dates are not formatted according to NSDate's calendar
969 // so we hardcode distantPast's value so that it looks like LLDB is doing
970 // the right thing.
971
972 // The relative time in seconds from Cocoa Epoch to [NSDate distantPast].
973 const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
974 if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
975 stream.Printf("0001-01-01 00:00:00 UTC");
976 return true;
977 }
978
979 // Accomodate for the __NSTaggedDate format introduced in Foundation 1600.
980 if (class_name == g_NSTaggedDate) {
981 auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
982 ObjCLanguageRuntime::Get(*process_sp));
983 if (runtime && runtime->GetFoundationVersion() >= 1600)
984 date_value = decodeTaggedTimeInterval(value_bits << 4);
985 }
986
987 // this snippet of code assumes that time_t == seconds since Jan-1-1970 this
988 // is generally true and POSIXly happy, but might break if a library vendor
989 // decides to get creative
990 time_t epoch = GetOSXEpoch();
991 epoch = epoch + static_cast<time_t>(std::floor(date_value));
992 tm *tm_date = gmtime(&epoch);
993 if (!tm_date)
994 return false;
995 std::string buffer(1024, 0);
996 if (strftime(&buffer[0], 1023, "%Z", tm_date) == 0)
997 return false;
998 stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900,
999 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
1000 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
1001 return true;
1002}
1003
1005 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
1006 ProcessSP process_sp = valobj.GetProcessSP();
1007 if (!process_sp)
1008 return false;
1009
1010 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
1011
1012 if (!runtime)
1013 return false;
1014
1016 runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
1017
1018 if (!descriptor || !descriptor->IsValid())
1019 return false;
1020
1021 ConstString class_name = descriptor->GetClassName();
1022
1023 if (class_name.IsEmpty())
1024 return false;
1025
1026 if (ConstString cs = Mangled(class_name).GetDemangledName())
1027 class_name = cs;
1028
1029 stream.Printf("%s", class_name.AsCString("<unknown class>"));
1030 return true;
1031}
1032
1034public:
1037
1039
1040 llvm::Expected<uint32_t> CalculateNumChildren() override { return 0; }
1041
1042 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
1043 return lldb::ValueObjectSP();
1044 }
1045
1049
1050 bool MightHaveChildren() override { return false; }
1051
1052 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
1053 return llvm::createStringError("Type has no child named '%s'",
1054 name.AsCString());
1055 }
1056};
1057
1063
1064template <bool needs_at>
1066 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
1067 ProcessSP process_sp = valobj.GetProcessSP();
1068 if (!process_sp)
1069 return false;
1070
1071 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
1072
1073 if (!runtime)
1074 return false;
1075
1077 runtime->GetClassDescriptor(valobj));
1078
1079 if (!descriptor || !descriptor->IsValid())
1080 return false;
1081
1082 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
1083 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
1084
1085 if (!valobj_addr)
1086 return false;
1087
1088 uint64_t value = 0;
1089
1090 llvm::StringRef class_name = descriptor->GetClassName().GetCString();
1091
1092 if (class_name.empty())
1093 return false;
1094
1095 bool isNSConcreteData = class_name == "NSConcreteData";
1096 bool isNSConcreteMutableData = class_name == "NSConcreteMutableData";
1097 bool isNSCFData = class_name == "__NSCFData";
1098 if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
1099 uint32_t offset;
1100 if (isNSConcreteData)
1101 offset = is_64bit ? 8 : 4;
1102 else
1103 offset = is_64bit ? 16 : 8;
1104
1105 Status error;
1106 value = process_sp->ReadUnsignedIntegerFromMemory(
1107 valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
1108 if (error.Fail())
1109 return false;
1110 } else if (class_name == "_NSInlineData") {
1111 uint32_t offset = (is_64bit ? 8 : 4);
1112 Status error;
1113 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
1114 0, error);
1115 if (error.Fail())
1116 return false;
1117 } else if (class_name == "_NSZeroData") {
1118 value = 0;
1119 } else
1120 return false;
1121
1122 stream.Printf("%s%" PRIu64 " byte%s%s", (needs_at ? "@\"" : ""), value,
1123 (value != 1 ? "s" : ""), (needs_at ? "\"" : ""));
1124
1125 return true;
1126}
1127
1129 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
1130 const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
1131
1132 ValueObjectSP real_guy_sp = valobj.GetSP();
1133
1134 if (type_info & eTypeIsPointer) {
1135 Status err;
1136 real_guy_sp = valobj.Dereference(err);
1137 if (err.Fail() || !real_guy_sp)
1138 return false;
1139 } else if (type_info & eTypeIsReference) {
1140 real_guy_sp = valobj.GetChildAtIndex(0);
1141 if (!real_guy_sp)
1142 return false;
1143 }
1144 int8_t value = (real_guy_sp->GetValueAsSigned(0) & 0xFF);
1145 switch (value) {
1146 case 0:
1147 stream.Printf("NO");
1148 break;
1149 case 1:
1150 stream.Printf("YES");
1151 break;
1152 default:
1153 stream.Printf("%d", value);
1154 break;
1155 }
1156 return true;
1157}
1158
1160 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
1161 lldb::addr_t valobj_ptr_value =
1163 if (valobj_ptr_value == LLDB_INVALID_ADDRESS)
1164 return false;
1165
1166 ProcessSP process_sp(valobj.GetProcessSP());
1167 if (!process_sp)
1168 return false;
1169
1170 if (AppleObjCRuntime *objc_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
1171 ObjCLanguageRuntime::Get(*process_sp))) {
1173 cf_false = LLDB_INVALID_ADDRESS;
1174 objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false);
1175 if (valobj_ptr_value == cf_true) {
1176 stream.PutCString("YES");
1177 return true;
1178 }
1179 if (valobj_ptr_value == cf_false) {
1180 stream.PutCString("NO");
1181 return true;
1182 }
1183 }
1184
1185 return false;
1186}
1187
1188template <bool is_sel_ptr>
1190 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
1191 lldb::ValueObjectSP valobj_sp;
1192
1193 CompilerType charstar(valobj.GetCompilerType()
1195 .GetPointerType());
1196
1197 if (!charstar)
1198 return false;
1199
1200 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1201
1202 if (is_sel_ptr) {
1204 if (data_address == LLDB_INVALID_ADDRESS)
1205 return false;
1206 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address,
1207 exe_ctx, charstar);
1208 } else {
1209 DataExtractor data;
1210 Status error;
1211 valobj.GetData(data, error);
1212 if (error.Fail())
1213 return false;
1214 valobj_sp =
1215 ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1216 }
1217
1218 if (!valobj_sp)
1219 return false;
1220
1221 stream.Printf("%s", valobj_sp->GetSummaryAsCString());
1222 return true;
1223}
1224
1225// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1226// this call gives the POSIX equivalent of the Cocoa epoch
1228 static time_t epoch = 0;
1229 if (!epoch) {
1230#if !defined(_WIN32) && !defined(_AIX)
1231 tzset();
1232 tm tm_epoch;
1233 tm_epoch.tm_sec = 0;
1234 tm_epoch.tm_hour = 0;
1235 tm_epoch.tm_min = 0;
1236 tm_epoch.tm_mon = 0;
1237 tm_epoch.tm_mday = 1;
1238 tm_epoch.tm_year = 2001 - 1900;
1239 tm_epoch.tm_isdst = -1;
1240 tm_epoch.tm_gmtoff = 0;
1241 tm_epoch.tm_zone = nullptr;
1242 epoch = timegm(&tm_epoch);
1243#endif
1244 }
1245 return epoch;
1246}
1247
1249 ValueObject &, Stream &, const TypeSummaryOptions &);
1250
1252 ValueObject &, Stream &, const TypeSummaryOptions &);
1253
1255 ValueObject &, Stream &, const TypeSummaryOptions &);
1256
1258 ValueObject &, Stream &, const TypeSummaryOptions &);
static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, int64_t value, lldb::LanguageType lang)
Definition Cocoa.cpp:380
static void NSNumber_FormatChar(ValueObject &valobj, Stream &stream, char value, lldb::LanguageType lang)
Definition Cocoa.cpp:341
static void NSNumber_FormatFloat(ValueObject &valobj, Stream &stream, float value, lldb::LanguageType lang)
Definition Cocoa.cpp:410
static double decodeTaggedTimeInterval(uint64_t encodedTimeInterval)
Definition Cocoa.cpp:882
static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value, lldb::LanguageType lang)
Definition Cocoa.cpp:367
static uint64_t decodeExponent(uint64_t exp)
Definition Cocoa.cpp:876
static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, const llvm::APInt &value, lldb::LanguageType lang)
Definition Cocoa.cpp:393
static void NSNumber_FormatDouble(ValueObject &valobj, Stream &stream, double value, lldb::LanguageType lang)
Definition Cocoa.cpp:423
const int TAGGED_DATE_EXPONENT_BIAS
Bias value for tagged pointer exponents.
Definition Cocoa.cpp:861
static void NSNumber_FormatShort(ValueObject &valobj, Stream &stream, short value, lldb::LanguageType lang)
Definition Cocoa.cpp:354
static llvm::raw_ostream & error(Stream &strm)
#define _C_USHT
#define _C_ULNG
#define _C_INT
#define _C_UINT
#define _C_CHR
#define _C_ULNG_LNG
#define _C_UCHR
#define _C_LNG
#define _C_LNG_LNG
#define _C_SHT
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
Definition Cocoa.cpp:1042
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Definition Cocoa.cpp:1052
llvm::Expected< uint32_t > CalculateNumChildren() override
Definition Cocoa.cpp:1040
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
Definition Cocoa.cpp:1046
~ObjCClassSyntheticChildrenFrontEnd() override=default
ObjCClassSyntheticChildrenFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition Cocoa.cpp:1035
Generic representation of a type in a programming language.
CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const
Create related types using the current type's AST.
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
bool IsEmpty() const
Test for empty string.
An data extractor class.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
static Language * FindPlugin(lldb::LanguageType language)
Definition Language.cpp:84
void void Printf(const char *format,...) __attribute__((format(printf
Prefer using LLDB_LOGF whenever possible.
Definition Log.cpp:156
A class that handles mangled names.
Definition Mangled.h:34
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa)
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:294
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
SyntheticChildrenFrontEnd(ValueObject &backend)
lldb::LanguageType GetLanguage() const
virtual uint64_t GetData(DataExtractor &data, Status &error)
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true)
CompilerType GetCompilerType()
lldb::ValueObjectSP GetSP()
lldb::ProcessSP GetProcessSP() const
virtual lldb::ValueObjectSP GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type, bool can_create, ConstString name_const_str=ConstString())
static lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
Given an address either create a value object containing the value at that address,...
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
static lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
virtual lldb::ValueObjectSP Dereference(Status &error)
const ExecutionContextRef & GetExecutionContextRef() const
#define UNUSED_IF_ASSERT_DISABLED(x)
#define LLDB_INVALID_ADDRESS
bool NSURLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:778
template bool NSDataSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool ObjCBOOLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1128
bool ObjCBooleanSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1159
bool NSBundleSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:38
bool NSIndexSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:233
bool NSDecimalNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:729
template bool ObjCSELSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
template bool ObjCSELSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSDataSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1065
bool NSDateSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:902
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:138
bool NSMachPortSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:187
template bool NSDataSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool ObjCSELSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1189
bool ObjCClassSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1004
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:436
bool NSTimeZoneSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:89
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSString.cpp:33
SyntheticChildrenFrontEnd * ObjCClassSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition Cocoa.cpp:1059
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
LanguageType
Programming language type.
std::shared_ptr< lldb_private::Process > ProcessSP
uint64_t addr_t
Definition lldb-types.h:80
uint64_t sign
Definition Cocoa.cpp:866
uint64_t exponent
Definition Cocoa.cpp:865
uint64_t fraction
Definition Cocoa.cpp:864
uint64_t unused
Definition Cocoa.cpp:873
uint64_t sign
Definition Cocoa.cpp:872
uint64_t exponent
Definition Cocoa.cpp:871
uint64_t fraction
Definition Cocoa.cpp:870