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