36 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
50 if (!descriptor.get() || !descriptor->IsValid())
53 uint32_t ptr_size = process_sp->GetAddressByteSize();
60 ConstString class_name_cs = descriptor->GetClassName();
61 llvm::StringRef class_name = class_name_cs.
GetStringRef();
63 if (class_name.empty())
67 bool is_tagged = descriptor->GetTaggedPointerInfo();
69 if (class_name ==
"NSTaggedPointerString")
73 if (class_name ==
"NSIndirectTaggedPointerString")
79 auto iter = additionals_map.find(class_name_cs), end = additionals_map.end();
81 return iter->second(valobj, stream, summary_options);
84 uint64_t info_bits_location = valobj_addr + ptr_size;
86 info_bits_location += 3;
90 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(
91 info_bits_location, 1, 0,
error);
95 bool is_mutable = (info_bits & 1) == 1;
96 bool is_inline = (info_bits & 0x60) == 0;
97 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
98 bool is_unicode = (info_bits & 0x10) == 0x10;
99 bool is_path_store = class_name ==
"NSPathStore2";
100 bool has_null = (info_bits & 8) == 8;
102 size_t explicit_length = 0;
103 if (!has_null && has_explicit_length && !is_path_store) {
105 if (is_mutable && !is_inline)
106 explicit_length_offset =
107 explicit_length_offset + ptr_size;
109 explicit_length = explicit_length + 0;
110 else if (!is_inline && !is_mutable)
111 explicit_length_offset =
112 explicit_length_offset + ptr_size;
114 explicit_length_offset = 0;
116 if (explicit_length_offset) {
117 explicit_length_offset = valobj_addr + explicit_length_offset;
118 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(
119 explicit_length_offset, 4, 0,
error);
123 const llvm::StringSet<> supported_string_classes = {
124 "NSString",
"CFMutableStringRef",
125 "CFStringRef",
"__NSCFConstantString",
126 "__NSCFString",
"NSCFConstantString",
127 "NSCFString",
"NSPathStore2"};
128 if (supported_string_classes.count(class_name) == 0) {
134 llvm::StringRef prefix, suffix;
136 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
143 uint64_t location = 2 * ptr_size + valobj_addr;
144 location = process_sp->ReadPointerFromMemory(location,
error);
147 if (has_explicit_length && is_unicode) {
159 StringPrinter::StringElementType::UTF16>(options);
171 StringPrinter::StringElementType::ASCII>(options);
173 }
else if (is_inline && has_explicit_length && !is_unicode &&
174 !is_path_store && !is_mutable) {
175 uint64_t location = 3 * ptr_size + valobj_addr;
186 StringPrinter::StringElementType::ASCII>(options);
187 }
else if (is_unicode) {
188 uint64_t location = valobj_addr + 2 * ptr_size;
190 if (!has_explicit_length) {
193 location += ptr_size;
195 location = process_sp->ReadPointerFromMemory(location,
error);
210 StringPrinter::StringElementType::UTF16>(options);
211 }
else if (is_path_store) {
213 uint64_t length_ivar_offset = 1 * ptr_size;
219 if (!length_valobj_sp)
222 explicit_length = length_valobj_sp->GetValueAsUnsigned(0) >> 20;
236 StringPrinter::StringElementType::UTF16>(options);
237 }
else if (is_inline) {
238 uint64_t location = valobj_addr + 2 * ptr_size;
239 if (!has_explicit_length) {
244 process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0,
error);
245 has_explicit_length = !(
error.Fail() || explicit_length == 0);
257 if (has_explicit_length)
259 StringPrinter::StringElementType::UTF8>(options);
262 StringPrinter::StringElementType::ASCII>(options);
264 uint64_t location = valobj_addr + 2 * ptr_size;
265 location = process_sp->ReadPointerFromMemory(location,
error);
268 if (has_explicit_length && !has_null)
279 StringPrinter::StringElementType::ASCII>(options);
320 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
324 uint64_t len_bits = 0, data_bits = 0;
325 if (!descriptor->GetTaggedPointerInfo(&len_bits, &data_bits,
nullptr))
328 static const int g_MaxNonBitmaskedLen = 7;
329 static const int g_SixbitMaxLen = 9;
330 static const int g_fiveBitMaxLen = 11;
332 static const char *sixBitToCharLookup =
"eilotrm.apdnsIc ufkMShjTRxgC4013"
333 "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
335 if (len_bits > g_fiveBitMaxLen)
338 llvm::StringRef prefix, suffix;
340 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
345 if (len_bits <= g_MaxNonBitmaskedLen) {
347 stream.
Printf(
"\"%s\"", (
const char *)&data_bits);
354 uint8_t shift_offset = 0;
356 if (len_bits <= g_SixbitMaxLen) {
364 std::vector<uint8_t> bytes;
365 bytes.resize(len_bits);
366 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits) {
367 uint8_t packed = data_bits & bitmask;
368 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
372 stream.
Printf(
"\"%s\"", &bytes[0]);
"lldb/Target/ExecutionContext.h" A class that contains an execution context.