31#include "llvm/ADT/APInt.h"
32#include "llvm/ADT/bit.h"
52 if (!descriptor || !descriptor->IsValid())
55 uint32_t ptr_size = process_sp->GetAddressByteSize();
62 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
64 if (class_name.empty())
67 if (class_name ==
"NSBundle") {
68 uint64_t offset = 5 * ptr_size;
78 bool was_nsstring_ok =
80 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
103 if (!descriptor || !descriptor->IsValid())
106 uint32_t ptr_size = process_sp->GetAddressByteSize();
113 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
115 if (class_name.empty())
118 if (class_name ==
"__NSTimeZone") {
119 uint64_t offset = ptr_size;
127 bool was_nsstring_ok =
129 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
152 if (!descriptor || !descriptor->IsValid())
155 uint32_t ptr_size = process_sp->GetAddressByteSize();
162 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
164 if (class_name.empty())
167 if (class_name ==
"NSConcreteNotification") {
168 uint64_t offset = ptr_size;
176 bool was_nsstring_ok =
178 if (was_nsstring_ok && summary_stream.
GetSize() > 0) {
201 if (!descriptor || !descriptor->IsValid())
204 uint32_t ptr_size = process_sp->GetAddressByteSize();
211 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
213 if (class_name.empty())
216 uint64_t port_number = 0;
218 if (class_name ==
"NSMachPort") {
219 uint64_t offset = (ptr_size == 4 ? 12 : 20);
221 port_number = process_sp->ReadUnsignedIntegerFromMemory(
222 offset + valobj_addr, 4, 0,
error);
223 if (
error.Success()) {
224 stream.
Printf(
"mach port: %u",
225 (uint32_t)(port_number & 0x00000000FFFFFFFF));
248 if (!descriptor || !descriptor->IsValid())
251 uint32_t ptr_size = process_sp->GetAddressByteSize();
258 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
260 if (class_name.empty())
266 if (class_name ==
"NSIndexSet" || class_name ==
"NSMutableIndexSet") {
276 descriptor->GetTaggedPointerInfo(
nullptr,
nullptr, &payload)) {
277 count = llvm::popcount(payload);
282 uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
283 valobj_addr + ptr_size, 4, 0,
error);
291 if ((mode & 2) == 2) {
293 uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory(
294 valobj_addr + 2 * ptr_size, 8, 0,
error);
297 count = llvm::popcount(bitfield);
307 if ((mode & 1) == 1) {
318 count = process_sp->ReadUnsignedIntegerFromMemory(
319 valobj_addr + 3 * ptr_size, ptr_size, 0,
error);
324 count = process_sp->ReadUnsignedIntegerFromMemory(
325 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
329 count = process_sp->ReadUnsignedIntegerFromMemory(count + 2 * ptr_size,
337 stream.
Printf(
"%" PRIu64
" index%s", count, (count == 1 ?
"" :
"es"));
343 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:char");
345 llvm::StringRef prefix, suffix;
347 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
350 stream.
Printf(
"%hhd", value);
356 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:short");
358 llvm::StringRef prefix, suffix;
360 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
363 stream.
Printf(
"%hd", value);
369 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int");
371 llvm::StringRef prefix, suffix;
373 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
376 stream.
Printf(
"%d", value);
382 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:long");
384 llvm::StringRef prefix, suffix;
386 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
389 stream.
Printf(
"%" PRId64
"", value);
394 const llvm::APInt &value,
396 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:int128_t");
398 llvm::StringRef prefix, suffix;
400 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
403 const int radix = 10;
404 const bool isSigned =
true;
405 std::string str = llvm::toString(value, radix, isSigned);
412 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:float");
414 llvm::StringRef prefix, suffix;
416 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
419 stream.
Printf(
"%f", value);
425 static constexpr llvm::StringLiteral g_TypeHint(
"NSNumber:double");
427 llvm::StringRef prefix, suffix;
429 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
432 stream.
Printf(
"%g", value);
442 Log *log =
GetLog(LLDBLog::DataFormatters);
451 if (!descriptor || !descriptor->IsValid())
454 uint32_t ptr_size = process_sp->GetAddressByteSize();
461 llvm::StringRef class_name(descriptor->GetClassName().GetCString());
463 if (class_name.empty())
466 if (class_name ==
"__NSCFBoolean")
469 if (class_name ==
"NSDecimalNumber")
472 if (class_name ==
"NSConstantIntegerNumber") {
474 int64_t value = process_sp->ReadSignedIntegerFromMemory(
475 valobj_addr + 2 * ptr_size, 8, 0,
error);
478 uint64_t encoding_addr = process_sp->ReadUnsignedIntegerFromMemory(
479 valobj_addr + ptr_size, ptr_size, 0,
error);
483 process_sp->ReadUnsignedIntegerFromMemory(encoding_addr, 1, 0,
error);
507 stream.
Printf(
"%" PRIu64, value);
514 if (class_name ==
"NSConstantFloatNumber") {
516 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
517 valobj_addr + ptr_size, 4, 0,
error);
520 float flt_value = 0.0f;
521 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
526 if (class_name ==
"NSConstantDoubleNumber") {
528 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
529 valobj_addr + ptr_size, 8, 0,
error);
532 double dbl_value = 0.0;
533 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
538 if (class_name ==
"NSNumber" || class_name ==
"__NSCFNumber") {
541 if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
546 "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
578 const bool new_format =
581 enum class TypeCodes :
int {
591 uint64_t data_location = valobj_addr + 2 * ptr_size;
595 uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
596 valobj_addr + ptr_size, ptr_size, 0,
error);
601 bool is_preserved_number = cfinfoa & 0x8;
602 if (is_preserved_number) {
605 "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
610 type_code =
static_cast<TypeCodes
>(cfinfoa & 0x7);
612 uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
613 valobj_addr + ptr_size, 1, 0,
error) &
621 type_code = TypeCodes::sint8;
624 type_code = TypeCodes::sint16;
627 type_code = TypeCodes::sint32;
633 type_code = TypeCodes::sint64;
636 type_code = TypeCodes::f32;
639 type_code = TypeCodes::f64;
647 bool success =
false;
649 case TypeCodes::sint8:
650 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
657 case TypeCodes::sint16:
658 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
666 case TypeCodes::sint32:
667 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
674 case TypeCodes::sint64:
675 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
682 case TypeCodes::f32: {
683 uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
684 data_location, 4, 0,
error);
687 float flt_value = 0.0f;
688 memcpy(&flt_value, &flt_as_int,
sizeof(flt_as_int));
693 case TypeCodes::f64: {
694 uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
695 data_location, 8, 0,
error);
698 double dbl_value = 0.0;
699 memcpy(&dbl_value, &dbl_as_lng,
sizeof(dbl_as_lng));
704 case TypeCodes::sint128:
707 words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
711 words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
715 llvm::APInt i128_value(128, words);
736 uint32_t ptr_size = process_sp->GetAddressByteSize();
739 int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
740 valobj_addr + ptr_size, 1, 0,
error);
744 uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
745 valobj_addr + ptr_size + 1, 1, 0,
error);
750 const bool is_negative = (length_and_negative >> 4) & 1;
753 uint8_t length = length_and_negative & 0xf;
754 const bool is_nan = is_negative && (length == 0);
766 uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
767 valobj_addr + ptr_size + 4, 8, 0,
error);
774 stream.
Printf(
"%" PRIu64
" x 10^%" PRIi8, mantissa, exponent);
792 if (!descriptor || !descriptor->IsValid())
795 uint32_t ptr_size = process_sp->GetAddressByteSize();
802 llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();
804 if (class_name !=
"NSURL")
807 uint64_t offset_text = ptr_size + ptr_size +
809 uint64_t offset_base = offset_text + ptr_size;
813 if (!text || text->GetValueAsUnsigned(0) == 0)
817 if (base && base->GetValueAsUnsigned(0)) {
819 base_summary.
Clear();
821 if (base_summary.
Empty())
828 static constexpr llvm::StringLiteral quote_char(
"\"");
829 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
830 llvm::StringRef prefix, suffix;
832 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
835 llvm::StringRef summary_str = summary.
GetString();
837 summary_str.consume_back(suffix) && summary_str.consume_back(quote_char);
838 assert(back_consumed);
841 llvm::StringRef base_summary_str = base_summary.
GetString();
842 bool front_consumed = base_summary_str.consume_front(prefix) &&
843 base_summary_str.consume_front(quote_char);
844 assert(front_consumed);
847 if (!summary_str.empty() && !base_summary_str.empty()) {
848 stream << summary_str <<
" -- " << base_summary_str;
883 if (encodedTimeInterval == 0)
885 if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
886 return (uint64_t)-0.0;
889 llvm::bit_cast<TaggedDoubleBits>(encodedTimeInterval);
890 assert(encodedBits.
unused == 0);
895 decodedBits.
sign = encodedBits.
sign;
899 return llvm::bit_cast<double>(decodedBits);
916 if (!descriptor || !descriptor->IsValid())
919 uint32_t ptr_size = process_sp->GetAddressByteSize();
926 uint64_t date_value_bits = 0;
927 double date_value = 0.0;
929 ConstString class_name = descriptor->GetClassName();
932 static const ConstString g_dunder_NSDate(
"__NSDate");
933 static const ConstString g_NSTaggedDate(
"__NSTaggedDate");
934 static const ConstString g_NSCalendarDate(
"NSCalendarDate");
935 static const ConstString g_NSConstantDate(
"NSConstantDate");
940 uint64_t info_bits = 0, value_bits = 0;
941 if ((class_name == g_NSDate) || (class_name == g_dunder_NSDate) ||
942 (class_name == g_NSTaggedDate) || (class_name == g_NSConstantDate)) {
943 if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
944 date_value_bits = ((value_bits << 8) | (info_bits << 4));
945 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
948 process_sp->GetTarget().GetArchitecture().GetTriple());
950 (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size;
952 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
953 valobj_addr + delta, 8, 0,
error);
954 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
958 }
else if (class_name == g_NSCalendarDate) {
960 date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(
961 valobj_addr + 2 * ptr_size, 8, 0,
error);
962 memcpy(&date_value, &date_value_bits,
sizeof(date_value_bits));
973 const double RelSecondsFromCocoaEpochToNSDateDistantPast = -63114076800;
974 if (date_value == RelSecondsFromCocoaEpochToNSDateDistantPast) {
975 stream.
Printf(
"0001-01-01 00:00:00 UTC");
980 if (class_name == g_NSTaggedDate) {
981 auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
983 if (runtime && runtime->GetFoundationVersion() >= 1600)
991 epoch = epoch +
static_cast<time_t
>(std::floor(date_value));
992 tm *tm_date = gmtime(&epoch);
995 std::string buffer(1024, 0);
996 if (strftime(&buffer[0], 1023,
"%Z", tm_date) == 0)
998 stream.
Printf(
"%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900,
999 tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour,
1000 tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
1018 if (!descriptor || !descriptor->IsValid())
1021 ConstString class_name = descriptor->GetClassName();
1063template <
bool needs_at>
1078 if (!descriptor || !descriptor->IsValid())
1081 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
1089 llvm::StringRef class_name = descriptor->GetClassName().GetCString();
1091 if (class_name.empty())
1094 bool isNSConcreteData = class_name ==
"NSConcreteData";
1095 bool isNSConcreteMutableData = class_name ==
"NSConcreteMutableData";
1096 bool isNSCFData = class_name ==
"__NSCFData";
1097 if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
1099 if (isNSConcreteData)
1100 offset = is_64bit ? 8 : 4;
1102 offset = is_64bit ? 16 : 8;
1105 value = process_sp->ReadUnsignedIntegerFromMemory(
1106 valobj_addr + offset, is_64bit ? 8 : 4, 0,
error);
1109 }
else if (class_name ==
"_NSInlineData") {
1110 uint32_t offset = (is_64bit ? 8 : 4);
1112 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
1116 }
else if (class_name ==
"_NSZeroData") {
1121 stream.
Printf(
"%s%" PRIu64
" byte%s%s", (needs_at ?
"@\"" :
""), value,
1122 (value != 1 ?
"s" :
""), (needs_at ?
"\"" :
""));
1133 if (type_info & eTypeIsPointer) {
1136 if (err.
Fail() || !real_guy_sp)
1138 }
else if (type_info & eTypeIsReference) {
1143 int8_t value = (real_guy_sp->GetValueAsSigned(0) & 0xFF);
1152 stream.
Printf(
"%d", value);
1169 if (
AppleObjCRuntime *objc_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
1173 objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false);
1174 if (valobj_ptr_value == cf_true) {
1178 if (valobj_ptr_value == cf_false) {
1187template <
bool is_sel_ptr>
1220 stream.
Printf(
"%s", valobj_sp->GetSummaryAsCString());
1227 static time_t epoch = 0;
1232 tm_epoch.tm_sec = 0;
1233 tm_epoch.tm_hour = 0;
1234 tm_epoch.tm_min = 0;
1235 tm_epoch.tm_mon = 0;
1236 tm_epoch.tm_mday = 1;
1237 tm_epoch.tm_year = 2001 - 1900;
1238 tm_epoch.tm_isdst = -1;
1239 tm_epoch.tm_gmtoff = 0;
1240 tm_epoch.tm_zone =
nullptr;
1241 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