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"));
308 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:char");
310 llvm::StringRef prefix, suffix;
312 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
315 stream.
Printf(
"%hhd", value);
321 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:short");
323 llvm::StringRef prefix, suffix;
325 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
328 stream.
Printf(
"%hd", value);
334 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int");
336 llvm::StringRef prefix, suffix;
338 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
341 stream.
Printf(
"%d", value);
347 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:long");
349 llvm::StringRef prefix, suffix;
351 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
354 stream.
Printf(
"%" PRId64
"", value);
359 const llvm::APInt &value,
361 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int128_t");
363 llvm::StringRef prefix, suffix;
365 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
368 const int radix = 10;
369 const bool isSigned =
true;
370 std::string str = llvm::toString(value, radix, isSigned);
377 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:float");
379 llvm::StringRef prefix, suffix;
381 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
384 stream.
Printf(
"%f", value);
390 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:double");
392 llvm::StringRef prefix, suffix;
394 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
397 stream.
Printf(
"%g", value);
407 Log *log =
GetLog(LLDBLog::DataFormatters);
416 if (!descriptor || !descriptor->IsValid())
419 uint32_t ptr_size = process_sp->GetAddressByteSize();
426 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
428 if (class_name.empty())
431 if (class_name ==
"__NSCFBoolean")
434 if (class_name ==
"NSDecimalNumber")
437 if (class_name ==
"NSConstantIntegerNumber") {
439 int64_t value = process_sp->ReadSignedIntegerFromMemory(
440 valobj_addr + 2 * ptr_size, 8, 0,
error);
443 uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory(
444 valobj_addr + ptr_size, ptr_size, 0,
error);
448 process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0,
error);
472 stream.
Printf(
"%" PRIu64, value);
479 if (class_name ==
"NSConstantFloatNumber") {
481 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
482 valobj_addr + ptr_size, 4, 0,
error);
485 float flt_value = 0.0f;
486 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
491 if (class_name ==
"NSConstantDoubleNumber") {
493 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
494 valobj_addr + ptr_size, 8, 0,
error);
497 double dbl_value = 0.0;
498 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
503 if (class_name ==
"NSNumber" || class_name ==
"__NSCFNumber") {
506 if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
511 "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
543 const bool new_format =
546 enum class TypeCodes :
int {
556 uint64_t data_location = valobj_addr + 2 * ptr_size;
560 uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
561 valobj_addr + ptr_size, ptr_size, 0,
error);
566 bool is_preserved_number = cfinfoa & 0x8;
567 if (is_preserved_number) {
570 "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
575 type_code =
static_cast<TypeCodes
>(cfinfoa & 0x7);
577 uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
578 valobj_addr + ptr_size, 1, 0,
error) &
586 type_code = TypeCodes::sint8;
589 type_code = TypeCodes::sint16;
592 type_code = TypeCodes::sint32;
598 type_code = TypeCodes::sint64;
601 type_code = TypeCodes::f32;
604 type_code = TypeCodes::f64;
612 bool success =
false;
614 case TypeCodes::sint8:
615 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
622 case TypeCodes::sint16:
623 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
631 case TypeCodes::sint32:
632 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
639 case TypeCodes::sint64:
640 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
647 case TypeCodes::f32: {
648 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
649 data_location, 4, 0,
error);
652 float flt_value = 0.0f;
653 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
658 case TypeCodes::f64: {
659 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
660 data_location, 8, 0,
error);
663 double dbl_value = 0.0;
664 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
669 case TypeCodes::sint128:
672 words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
676 words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
680 llvm::APInt i128_value(128, words);
701 uint32_t ptr_size = process_sp->GetAddressByteSize();
704 int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
705 valobj_addr + ptr_size, 1, 0,
error);
709 uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
710 valobj_addr + ptr_size + 1, 1, 0,
error);
715 const bool is_negative = (length_and_negative >> 4) & 1;
718 uint8_t length = length_and_negative & 0xf;
719 const bool is_nan = is_negative && (length == 0);
731 uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
732 valobj_addr + ptr_size + 4, 8, 0,
error);
739 stream.
Printf(
"%" PRIu64
" x 10^%" PRIi8, mantissa, exponent);
757 if (!descriptor || !descriptor->IsValid())
760 uint32_t ptr_size = process_sp->GetAddressByteSize();
767 llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();
769 if (!class_name.equals(
"NSURL"))
772 uint64_t offset_text = ptr_size + ptr_size +
774 uint64_t offset_base = offset_text + ptr_size;
778 if (!text || text->GetValueAsUnsigned(0) == 0)
782 if (base && base->GetValueAsUnsigned(0)) {
784 base_summary.
Clear();
786 if (base_summary.
Empty())
793 static constexpr llvm::StringLiteral quote_char(
"\"");
794 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
795 llvm::StringRef prefix, suffix;
797 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
800 llvm::StringRef summary_str = summary.
GetString();
802 summary_str.consume_back(suffix) && summary_str.consume_back(quote_char);
803 assert(back_consumed);
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);
812 if (!summary_str.empty() && !base_summary_str.empty()) {
813 stream << summary_str <<
" -- " << base_summary_str;
848 if (encodedTimeInterval == 0)
850 if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
851 return (uint64_t)-0.0;
854 llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval);
855 assert(encodedBits.
unused == 0);
860 decodedBits.
sign = encodedBits.
sign;
864 return llvm::bit_cast<double>(decodedBits);
881 if (!descriptor || !descriptor->IsValid())
884 uint32_t ptr_size = process_sp->GetAddressByteSize();
891 uint64_t date_value_bits = 0;
892 double date_value = 0.0;
894 ConstString class_name = descriptor->GetClassName();
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");
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));
913 process_sp->GetTarget().GetArchitecture().GetTriple());
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));
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));
938 const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
939 if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
940 stream.
Printf(
"0001-01-01 00:00:00 UTC");
945 if (class_name == g_NSTaggedDate) {
946 auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
948 if (runtime && runtime->GetFoundationVersion() >= 1600)
956 epoch = epoch +
static_cast<time_t
>(std::floor(date_value));
957 tm *tm_date = gmtime(&epoch);
960 std::string buffer(1024, 0);
961 if (strftime(&buffer[0], 1023,
"%Z", tm_date) == 0)
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());
983 if (!descriptor || !descriptor->IsValid())
986 ConstString class_name = descriptor->GetClassName();
991 if (
ConstString cs = Mangled(class_name).GetDemangledName())
1008 return lldb::ValueObjectSP();
1026template <
bool needs_at>
1041 if (!descriptor || !descriptor->IsValid())
1044 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
1052 llvm::StringRef class_name = descriptor->GetClassName().GetCString();
1054 if (class_name.empty())
1057 bool isNSConcreteData = class_name ==
"NSConcreteData";
1058 bool isNSConcreteMutableData = class_name ==
"NSConcreteMutableData";
1059 bool isNSCFData = class_name ==
"__NSCFData";
1060 if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
1062 if (isNSConcreteData)
1063 offset = is_64bit ? 8 : 4;
1065 offset = is_64bit ? 16 : 8;
1068 value = process_sp->ReadUnsignedIntegerFromMemory(
1069 valobj_addr + offset, is_64bit ? 8 : 4, 0,
error);
1072 }
else if (class_name ==
"_NSInlineData") {
1073 uint32_t offset = (is_64bit ? 8 : 4);
1075 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
1079 }
else if (class_name ==
"_NSZeroData") {
1084 stream.
Printf(
"%s%" PRIu64
" byte%s%s", (needs_at ?
"@\"" :
""), value,
1085 (value != 1 ?
"s" :
""), (needs_at ?
"\"" :
""));
1094 ValueObjectSP real_guy_sp = valobj.
GetSP();
1096 if (type_info & eTypeIsPointer) {
1099 if (err.
Fail() || !real_guy_sp)
1101 }
else if (type_info & eTypeIsReference) {
1106 int8_t value = (real_guy_sp->GetValueAsSigned(0) & 0xFF);
1115 stream.
Printf(
"%d", value);
1132 if (
AppleObjCRuntime *objc_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
1136 objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false);
1137 if (valobj_ptr_value == cf_true) {
1141 if (valobj_ptr_value == cf_false) {
1150template <
bool is_sel_ptr>
1153 lldb::ValueObjectSP valobj_sp;
1183 stream.
Printf(
"%s", valobj_sp->GetSummaryAsCString());
1190 static time_t epoch = 0;
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);
static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, int64_t value, lldb::LanguageType lang)
static void NSNumber_FormatChar(ValueObject &valobj, Stream &stream, char value, lldb::LanguageType lang)
static void NSNumber_FormatFloat(ValueObject &valobj, Stream &stream, float value, lldb::LanguageType lang)
static double decodeTaggedTimeInterval(uint64_t encodedTimeInterval)
static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value, lldb::LanguageType lang)
static uint64_t decodeExponent(uint64_t exp)
static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, const llvm::APInt &value, lldb::LanguageType lang)
static void NSNumber_FormatDouble(ValueObject &valobj, Stream &stream, double value, lldb::LanguageType lang)
const int TAGGED_DATE_EXPONENT_BIAS
Bias value for tagged pointer exponents.
static void NSNumber_FormatShort(ValueObject &valobj, Stream &stream, short value, lldb::LanguageType lang)
static llvm::raw_ostream & error(Stream &strm)
time_t timegm(struct tm *t)
size_t GetIndexOfChildWithName(ConstString name) override
size_t CalculateNumChildren() override
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
~ObjCClassSyntheticChildrenFrontEnd() override=default
bool MightHaveChildren() override
ObjCClassSyntheticChildrenFrontEnd(lldb::ValueObjectSP valobj_sp)
uint32_t GetFoundationVersion()
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.
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.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
static Language * FindPlugin(lldb::LanguageType language)
void void Printf(const char *format,...) __attribute__((format(printf
Prefer using LLDB_LOGF whenever possible.
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa)
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
bool Fail() const
Test for error condition.
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
lldb::LanguageType GetLanguage() const
virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create)
virtual uint64_t GetData(DataExtractor &data, Status &error)
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())
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
#define UNUSED_IF_ASSERT_DISABLED(x)
#define LLDB_INVALID_ADDRESS
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.
LanguageType
Programming language type.