31#include "llvm/ADT/APInt.h"
32#include "llvm/ADT/bit.h"
53 if (!descriptor || !descriptor->IsValid())
56 uint32_t ptr_size = process_sp->GetAddressByteSize();
63 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
65 if (class_name.empty())
68 if (class_name ==
"NSBundle") {
69 uint64_t offset = 5 * ptr_size;
79 bool was_nsstring_ok =
81 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
104 if (!descriptor || !descriptor->IsValid())
107 uint32_t ptr_size = process_sp->GetAddressByteSize();
114 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
116 if (class_name.empty())
119 if (class_name ==
"__NSTimeZone") {
120 uint64_t offset = ptr_size;
128 bool was_nsstring_ok =
130 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
153 if (!descriptor || !descriptor->IsValid())
156 uint32_t ptr_size = process_sp->GetAddressByteSize();
163 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
165 if (class_name.empty())
168 if (class_name ==
"NSConcreteNotification") {
169 uint64_t offset = ptr_size;
177 bool was_nsstring_ok =
179 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
202 if (!descriptor || !descriptor->IsValid())
205 uint32_t ptr_size = process_sp->GetAddressByteSize();
212 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
214 if (class_name.empty())
217 uint64_t port_number = 0;
219 if (class_name ==
"NSMachPort") {
220 uint64_t offset = (ptr_size == 4 ? 12 : 20);
222 port_number = process_sp->ReadUnsignedIntegerFromMemory(
223 offset + valobj_addr, 4, 0,
error);
224 if (
error.Success()) {
225 stream.
Printf(
"mach port: %u",
226 (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") {
277 && descriptor->GetTaggedPointerInfo(
nullptr,
nullptr, &payload)) {
278 count = llvm::popcount(payload);
283 uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
284 valobj_addr + ptr_size, 4, 0,
error);
292 if ((mode & 2) == 2) {
294 uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory(
295 valobj_addr + 2 * ptr_size, 8, 0,
error);
298 count = llvm::popcount(bitfield);
308 if ((mode & 1) == 1) {
319 count = process_sp->ReadUnsignedIntegerFromMemory(
320 valobj_addr + 3 * ptr_size, ptr_size, 0,
error);
325 count = process_sp->ReadUnsignedIntegerFromMemory(
326 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
330 count = process_sp->ReadUnsignedIntegerFromMemory(count + 2 * ptr_size,
338 stream.
Printf(
"%" PRIu64
" index%s", count, (count == 1 ?
"" :
"es"));
344 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:char");
346 llvm::StringRef prefix, suffix;
348 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
351 stream.
Printf(
"%hhd", value);
357 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:short");
359 llvm::StringRef prefix, suffix;
361 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
364 stream.
Printf(
"%hd", value);
370 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int");
372 llvm::StringRef prefix, suffix;
374 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
377 stream.
Printf(
"%d", value);
383 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:long");
385 llvm::StringRef prefix, suffix;
387 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
390 stream.
Printf(
"%" PRId64
"", value);
395 const llvm::APInt &value,
397 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int128_t");
399 llvm::StringRef prefix, suffix;
401 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
404 const int radix = 10;
405 const bool isSigned =
true;
406 std::string str = llvm::toString(value, radix, isSigned);
413 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:float");
415 llvm::StringRef prefix, suffix;
417 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
420 stream.
Printf(
"%f", value);
426 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:double");
428 llvm::StringRef prefix, suffix;
430 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
433 stream.
Printf(
"%g", value);
443 Log *log =
GetLog(LLDBLog::DataFormatters);
452 if (!descriptor || !descriptor->IsValid())
455 uint32_t ptr_size = process_sp->GetAddressByteSize();
462 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
464 if (class_name.empty())
467 if (class_name ==
"__NSCFBoolean")
470 if (class_name ==
"NSDecimalNumber")
473 if (class_name ==
"NSConstantIntegerNumber") {
475 int64_t value = process_sp->ReadSignedIntegerFromMemory(
476 valobj_addr + 2 * ptr_size, 8, 0,
error);
479 uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory(
480 valobj_addr + ptr_size, ptr_size, 0,
error);
484 process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0,
error);
508 stream.
Printf(
"%" PRIu64, value);
515 if (class_name ==
"NSConstantFloatNumber") {
517 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
518 valobj_addr + ptr_size, 4, 0,
error);
521 float flt_value = 0.0f;
522 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
527 if (class_name ==
"NSConstantDoubleNumber") {
529 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
530 valobj_addr + ptr_size, 8, 0,
error);
533 double dbl_value = 0.0;
534 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
539 if (class_name ==
"NSNumber" || class_name ==
"__NSCFNumber") {
542 if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
547 "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
579 const bool new_format =
582 enum class TypeCodes :
int {
592 uint64_t data_location = valobj_addr + 2 * ptr_size;
596 uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
597 valobj_addr + ptr_size, ptr_size, 0,
error);
602 bool is_preserved_number = cfinfoa & 0x8;
603 if (is_preserved_number) {
606 "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
611 type_code =
static_cast<TypeCodes
>(cfinfoa & 0x7);
613 uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
614 valobj_addr + ptr_size, 1, 0,
error) &
622 type_code = TypeCodes::sint8;
625 type_code = TypeCodes::sint16;
628 type_code = TypeCodes::sint32;
634 type_code = TypeCodes::sint64;
637 type_code = TypeCodes::f32;
640 type_code = TypeCodes::f64;
648 bool success =
false;
650 case TypeCodes::sint8:
651 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
658 case TypeCodes::sint16:
659 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
667 case TypeCodes::sint32:
668 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
675 case TypeCodes::sint64:
676 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
683 case TypeCodes::f32: {
684 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
685 data_location, 4, 0,
error);
688 float flt_value = 0.0f;
689 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
694 case TypeCodes::f64: {
695 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
696 data_location, 8, 0,
error);
699 double dbl_value = 0.0;
700 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
705 case TypeCodes::sint128:
708 words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
712 words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
716 llvm::APInt i128_value(128, words);
737 uint32_t ptr_size = process_sp->GetAddressByteSize();
740 int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
741 valobj_addr + ptr_size, 1, 0,
error);
745 uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
746 valobj_addr + ptr_size + 1, 1, 0,
error);
751 const bool is_negative = (length_and_negative >> 4) & 1;
754 uint8_t length = length_and_negative & 0xf;
755 const bool is_nan = is_negative && (length == 0);
767 uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
768 valobj_addr + ptr_size + 4, 8, 0,
error);
775 stream.
Printf(
"%" PRIu64
" x 10^%" PRIi8, mantissa, exponent);
793 if (!descriptor || !descriptor->IsValid())
796 uint32_t ptr_size = process_sp->GetAddressByteSize();
803 llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();
805 if (class_name !=
"NSURL")
808 uint64_t offset_text = ptr_size + ptr_size +
810 uint64_t offset_base = offset_text + ptr_size;
814 if (!text || text->GetValueAsUnsigned(0) == 0)
818 if (base && base->GetValueAsUnsigned(0)) {
820 base_summary.
Clear();
822 if (base_summary.
Empty())
829 static constexpr llvm::StringLiteral quote_char(
"\"");
830 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
831 llvm::StringRef prefix, suffix;
833 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
836 llvm::StringRef summary_str = summary.
GetString();
838 summary_str.consume_back(suffix) && summary_str.consume_back(quote_char);
839 assert(back_consumed);
842 llvm::StringRef base_summary_str = base_summary.
GetString();
843 bool front_consumed = base_summary_str.consume_front(prefix) &&
844 base_summary_str.consume_front(quote_char);
845 assert(front_consumed);
848 if (!summary_str.empty() && !base_summary_str.empty()) {
849 stream << summary_str <<
" -- " << base_summary_str;
884 if (encodedTimeInterval == 0)
886 if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
887 return (uint64_t)-0.0;
890 llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval);
891 assert(encodedBits.
unused == 0);
896 decodedBits.
sign = encodedBits.
sign;
900 return llvm::bit_cast<double>(decodedBits);
917 if (!descriptor || !descriptor->IsValid())
920 uint32_t ptr_size = process_sp->GetAddressByteSize();
927 uint64_t date_value_bits = 0;
928 double date_value = 0.0;
930 ConstString class_name = descriptor->GetClassName();
933 static const ConstString g_dunder_NSDate(
"__NSDate");
934 static const ConstString g_NSTaggedDate(
"__NSTaggedDate");
935 static const ConstString g_NSCalendarDate(
"NSCalendarDate");
936 static const ConstString g_NSConstantDate(
"NSConstantDate");
941 uint64_t info_bits = 0, value_bits = 0;
942 if ((class_name == g_NSDate) || (class_name == g_dunder_NSDate) ||
943 (class_name == g_NSTaggedDate) || (class_name == g_NSConstantDate)) {
944 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
945 date_value_bits = ((value_bits << 8) | (info_bits << 4));
946 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
949 process_sp->GetTarget().GetArchitecture().GetTriple());
951 (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size;
953 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
954 valobj_addr + delta, 8, 0,
error);
955 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
959 }
else if (class_name == g_NSCalendarDate) {
961 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
962 valobj_addr + 2 * ptr_size, 8, 0,
error);
963 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
974 const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
975 if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
976 stream.
Printf(
"0001-01-01 00:00:00 UTC");
981 if (class_name == g_NSTaggedDate) {
982 auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
984 if (runtime && runtime->GetFoundationVersion() >= 1600)
992 epoch = epoch +
static_cast<time_t
>(std::floor(date_value));
993 tm *tm_date = gmtime(&epoch);
996 std::string buffer(1024, 0);
997 if (strftime(&buffer[0], 1023,
"%Z", tm_date) == 0)
999 stream.
Printf(
"%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900,
1000 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
1001 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
1019 if (!descriptor || !descriptor->IsValid())
1022 ConstString class_name = descriptor->GetClassName();
1064template <
bool needs_at>
1079 if (!descriptor || !descriptor->IsValid())
1082 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
1090 llvm::StringRef class_name = descriptor->GetClassName().GetCString();
1092 if (class_name.empty())
1095 bool isNSConcreteData = class_name ==
"NSConcreteData";
1096 bool isNSConcreteMutableData = class_name ==
"NSConcreteMutableData";
1097 bool isNSCFData = class_name ==
"__NSCFData";
1098 if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
1100 if (isNSConcreteData)
1101 offset = is_64bit ? 8 : 4;
1103 offset = is_64bit ? 16 : 8;
1106 value = process_sp->ReadUnsignedIntegerFromMemory(
1107 valobj_addr + offset, is_64bit ? 8 : 4, 0,
error);
1110 }
else if (class_name ==
"_NSInlineData") {
1111 uint32_t offset = (is_64bit ? 8 : 4);
1113 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
1117 }
else if (class_name ==
"_NSZeroData") {
1122 stream.
Printf(
"%s%" PRIu64
" byte%s%s", (needs_at ?
"@\"" :
""), value,
1123 (value != 1 ?
"s" :
""), (needs_at ?
"\"" :
""));
1134 if (type_info & eTypeIsPointer) {
1137 if (err.
Fail() || !real_guy_sp)
1139 }
else if (type_info & eTypeIsReference) {
1144 int8_t value = (real_guy_sp->GetValueAsSigned(0) & 0xFF);
1153 stream.
Printf(
"%d", value);
1170 if (
AppleObjCRuntime *objc_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
1174 objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false);
1175 if (valobj_ptr_value == cf_true) {
1179 if (valobj_ptr_value == cf_false) {
1188template <
bool is_sel_ptr>
1221 stream.
Printf(
"%s", valobj_sp->GetSummaryAsCString());
1228 static time_t epoch = 0;
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);
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)
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< uint32_t > CalculateNumChildren() override
size_t GetIndexOfChildWithName(ConstString name) override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
~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.
A class that handles mangled names.
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 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
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.
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