32 #include "llvm/ADT/APInt.h"
33 #include "llvm/ADT/bit.h"
54 if (!descriptor || !descriptor->IsValid())
57 uint32_t ptr_size = process_sp->GetAddressByteSize();
64 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
66 if (class_name.empty())
69 if (class_name ==
"NSBundle") {
70 uint64_t offset = 5 * ptr_size;
80 bool was_nsstring_ok =
82 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
105 if (!descriptor || !descriptor->IsValid())
108 uint32_t ptr_size = process_sp->GetAddressByteSize();
115 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
117 if (class_name.empty())
120 if (class_name ==
"__NSTimeZone") {
121 uint64_t offset = ptr_size;
129 bool was_nsstring_ok =
131 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
154 if (!descriptor || !descriptor->IsValid())
157 uint32_t ptr_size = process_sp->GetAddressByteSize();
164 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
166 if (class_name.empty())
169 if (class_name ==
"NSConcreteNotification") {
170 uint64_t offset = ptr_size;
178 bool was_nsstring_ok =
180 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
203 if (!descriptor || !descriptor->IsValid())
206 uint32_t ptr_size = process_sp->GetAddressByteSize();
213 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
215 if (class_name.empty())
218 uint64_t port_number = 0;
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));
249 if (!descriptor || !descriptor->IsValid())
252 uint32_t ptr_size = process_sp->GetAddressByteSize();
259 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
261 if (class_name.empty())
267 if (class_name ==
"NSIndexSet" || class_name ==
"NSMutableIndexSet") {
269 uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
270 valobj_addr + ptr_size, 4, 0,
error);
274 if ((mode & 1) == 1) {
283 count = process_sp->ReadUnsignedIntegerFromMemory(
284 valobj_addr + 3 * ptr_size, ptr_size, 0,
error);
289 count = process_sp->ReadUnsignedIntegerFromMemory(
290 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
294 count = process_sp->ReadUnsignedIntegerFromMemory(count + 2 * ptr_size,
302 stream.
Printf(
"%" PRIu64
" index%s", count, (count == 1 ?
"" :
"es"));
311 if (
Language *language = Language::FindPlugin(lang)) {
312 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
319 stream.
Printf(
"%s%hhd%s", prefix.c_str(), value, suffix.c_str());
327 if (
Language *language = Language::FindPlugin(lang)) {
328 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
335 stream.
Printf(
"%s%hd%s", prefix.c_str(), value, suffix.c_str());
343 if (
Language *language = Language::FindPlugin(lang)) {
344 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
351 stream.
Printf(
"%s%d%s", prefix.c_str(), value, suffix.c_str());
359 if (
Language *language = Language::FindPlugin(lang)) {
360 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
367 stream.
Printf(
"%s%" PRId64
"%s", prefix.c_str(), value, suffix.c_str());
371 const llvm::APInt &value,
373 static ConstString g_TypeHint(
"NSNumber:int128_t");
376 if (
Language *language = Language::FindPlugin(lang)) {
377 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
385 const int radix = 10;
386 const bool isSigned =
true;
397 if (
Language *language = Language::FindPlugin(lang)) {
398 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
405 stream.
Printf(
"%s%f%s", prefix.c_str(), value, suffix.c_str());
413 if (
Language *language = Language::FindPlugin(lang)) {
414 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
421 stream.
Printf(
"%s%g%s", prefix.c_str(), value, suffix.c_str());
430 Log *log =
GetLog(LLDBLog::DataFormatters);
439 if (!descriptor || !descriptor->IsValid())
442 uint32_t ptr_size = process_sp->GetAddressByteSize();
449 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
451 if (class_name.empty())
454 if (class_name ==
"__NSCFBoolean")
457 if (class_name ==
"NSDecimalNumber")
460 if (class_name ==
"NSConstantIntegerNumber") {
462 int64_t value = process_sp->ReadSignedIntegerFromMemory(
463 valobj_addr + 2 * ptr_size, 8, 0,
error);
466 uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory(
467 valobj_addr + ptr_size, ptr_size, 0,
error);
471 process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0,
error);
495 stream.
Printf(
"%" PRIu64, value);
502 if (class_name ==
"NSConstantFloatNumber") {
504 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
505 valobj_addr + ptr_size, 4, 0,
error);
508 float flt_value = 0.0f;
509 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
514 if (class_name ==
"NSConstantDoubleNumber") {
516 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
517 valobj_addr + ptr_size, 8, 0,
error);
520 double dbl_value = 0.0;
521 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
526 if (class_name ==
"NSNumber" || class_name ==
"__NSCFNumber") {
529 if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
534 "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
564 ObjCLanguageRuntime::Get(*process_sp));
566 const bool new_format =
569 enum class TypeCodes : int {
579 uint64_t data_location = valobj_addr + 2 * ptr_size;
583 uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
584 valobj_addr + ptr_size, ptr_size, 0,
error);
589 bool is_preserved_number = cfinfoa & 0x8;
590 if (is_preserved_number) {
593 "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
598 type_code =
static_cast<TypeCodes
>(cfinfoa & 0x7);
600 uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
601 valobj_addr + ptr_size, 1, 0,
error) &
609 type_code = TypeCodes::sint8;
612 type_code = TypeCodes::sint16;
615 type_code = TypeCodes::sint32;
621 type_code = TypeCodes::sint64;
624 type_code = TypeCodes::f32;
627 type_code = TypeCodes::f64;
635 bool success =
false;
637 case TypeCodes::sint8:
638 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
645 case TypeCodes::sint16:
646 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
654 case TypeCodes::sint32:
655 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
662 case TypeCodes::sint64:
663 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
670 case TypeCodes::f32: {
671 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
672 data_location, 4, 0,
error);
675 float flt_value = 0.0f;
676 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
681 case TypeCodes::f64: {
682 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
683 data_location, 8, 0,
error);
686 double dbl_value = 0.0;
687 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
692 case TypeCodes::sint128:
695 words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
699 words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
703 llvm::APInt i128_value(128, words);
724 uint32_t ptr_size = process_sp->GetAddressByteSize();
727 int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
728 valobj_addr + ptr_size, 1, 0,
error);
732 uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
733 valobj_addr + ptr_size + 1, 1, 0,
error);
738 const bool is_negative = (length_and_negative >> 4) & 1;
741 uint8_t length = length_and_negative & 0xf;
742 const bool is_nan = is_negative && (length == 0);
754 uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
755 valobj_addr + ptr_size + 4, 8, 0,
error);
762 stream.
Printf(
"%" PRIu64
" x 10^%" PRIi8, mantissa, exponent);
780 if (!descriptor || !descriptor->IsValid())
783 uint32_t ptr_size = process_sp->GetAddressByteSize();
790 llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();
792 if (!class_name.equals(
"NSURL"))
795 uint64_t offset_text = ptr_size + ptr_size +
797 uint64_t offset_base = offset_text + ptr_size;
801 if (!text || text->GetValueAsUnsigned(0) == 0)
805 if (base && base->GetValueAsUnsigned(0)) {
807 base_summary.
Clear();
809 if (base_summary.
Empty())
816 const char quote_char =
'"';
819 if (!language->GetFormatterPrefixSuffix(*text,
ConstString(
"NSString"),
826 llvm::StringRef summary_str = summary.
GetString();
827 bool back_consumed = summary_str.consume_back(quote_char + suffix);
828 assert(back_consumed);
831 llvm::StringRef base_summary_str = base_summary.
GetString();
832 bool front_consumed = base_summary_str.consume_front(prefix + quote_char);
833 assert(front_consumed);
836 if (!summary_str.empty() && !base_summary_str.empty()) {
837 stream.
Printf(
"%s -- %s", summary_str.str().c_str(),
838 base_summary_str.str().c_str());
873 if (encodedTimeInterval == 0)
875 if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
876 return (uint64_t)-0.0;
879 llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval);
880 assert(encodedBits.
unused == 0);
885 decodedBits.
sign = encodedBits.
sign;
889 return llvm::bit_cast<double>(decodedBits);
906 if (!descriptor || !descriptor->IsValid())
909 uint32_t ptr_size = process_sp->GetAddressByteSize();
916 uint64_t date_value_bits = 0;
917 double date_value = 0.0;
919 ConstString class_name = descriptor->GetClassName();
922 static const ConstString g_dunder_NSDate(
"__NSDate");
923 static const ConstString g_NSTaggedDate(
"__NSTaggedDate");
924 static const ConstString g_NSCalendarDate(
"NSCalendarDate");
925 static const ConstString g_NSConstantDate(
"NSConstantDate");
930 uint64_t info_bits = 0, value_bits = 0;
931 if ((class_name == g_NSDate) || (class_name == g_dunder_NSDate) ||
932 (class_name == g_NSTaggedDate) || (class_name == g_NSConstantDate)) {
933 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
934 date_value_bits = ((value_bits << 8) | (info_bits << 4));
935 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
938 process_sp->GetTarget().GetArchitecture().GetTriple());
940 (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size;
942 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
943 valobj_addr + delta, 8, 0,
error);
944 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
948 }
else if (class_name == g_NSCalendarDate) {
950 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
951 valobj_addr + 2 * ptr_size, 8, 0,
error);
952 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
963 const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
964 if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
965 stream.
Printf(
"0001-01-01 00:00:00 UTC");
970 if (class_name == g_NSTaggedDate) {
971 auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
972 ObjCLanguageRuntime::Get(*process_sp));
973 if (runtime && runtime->GetFoundationVersion() >= 1600)
981 epoch = epoch +
static_cast<time_t
>(std::floor(date_value));
982 tm *tm_date = gmtime(&epoch);
986 if (strftime(&buffer[0], 1023,
"%Z", tm_date) == 0)
988 stream.
Printf(
"%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900,
989 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
990 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
1008 if (!descriptor || !descriptor->IsValid())
1011 ConstString class_name = descriptor->GetClassName();
1016 if (
ConstString cs = Mangled(class_name).GetDemangledName())
1033 return lldb::ValueObjectSP();
1051 template <
bool needs_at>
1066 if (!descriptor || !descriptor->IsValid())
1069 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
1077 llvm::StringRef class_name = descriptor->GetClassName().GetCString();
1079 if (class_name.empty())
1082 bool isNSConcreteData = class_name ==
"NSConcreteData";
1083 bool isNSConcreteMutableData = class_name ==
"NSConcreteMutableData";
1084 bool isNSCFData = class_name ==
"__NSCFData";
1085 if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
1087 if (isNSConcreteData)
1088 offset = is_64bit ? 8 : 4;
1090 offset = is_64bit ? 16 : 8;
1093 value = process_sp->ReadUnsignedIntegerFromMemory(
1094 valobj_addr + offset, is_64bit ? 8 : 4, 0,
error);
1097 }
else if (class_name ==
"_NSInlineData") {
1098 uint32_t offset = (is_64bit ? 8 : 4);
1100 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
1104 }
else if (class_name ==
"_NSZeroData") {
1109 stream.
Printf(
"%s%" PRIu64
" byte%s%s", (needs_at ?
"@\"" :
""), value,
1110 (value != 1 ?
"s" :
""), (needs_at ?
"\"" :
""));
1119 ValueObjectSP real_guy_sp = valobj.
GetSP();
1121 if (type_info & eTypeIsPointer) {
1124 if (err.
Fail() || !real_guy_sp)
1126 }
else if (type_info & eTypeIsReference) {
1131 int8_t value = (real_guy_sp->GetValueAsSigned(0) & 0xFF);
1140 stream.
Printf(
"%d", value);
1157 if (
AppleObjCRuntime *objc_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
1158 ObjCLanguageRuntime::Get(*process_sp))) {
1161 objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false);
1162 if (valobj_ptr_value == cf_true) {
1166 if (valobj_ptr_value == cf_false) {
1175 template <
bool is_sel_ptr>
1178 lldb::ValueObjectSP valobj_sp;
1193 valobj_sp = ValueObject::CreateValueObjectFromAddress(
"text", data_address,
1202 ValueObject::CreateValueObjectFromData(
"text", data, exe_ctx, charstar);
1208 stream.
Printf(
"%s", valobj_sp->GetSummaryAsCString());
1215 static time_t epoch = 0;
1220 tm_epoch.tm_sec = 0;
1221 tm_epoch.tm_hour = 0;
1222 tm_epoch.tm_min = 0;
1223 tm_epoch.tm_mon = 0;
1224 tm_epoch.tm_mday = 1;
1225 tm_epoch.tm_year = 2001 - 1900;
1226 tm_epoch.tm_isdst = -1;
1227 tm_epoch.tm_gmtoff = 0;
1228 tm_epoch.tm_zone =
nullptr;
1229 epoch =
timegm(&tm_epoch);