38 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
52 if (!descriptor.get() || !descriptor->IsValid())
55 uint32_t ptr_size = process_sp->GetAddressByteSize();
62 ConstString class_name_cs = descriptor->GetClassName();
63 llvm::StringRef class_name = class_name_cs.
GetStringRef();
65 if (class_name.empty())
69 bool is_tagged = descriptor->GetTaggedPointerInfo();
71 if (class_name ==
"NSTaggedPointerString")
75 if (class_name ==
"NSIndirectTaggedPointerString")
81 auto iter = additionals_map.find(class_name_cs), end = additionals_map.end();
83 return iter->second(valobj, stream, summary_options);
86 uint64_t info_bits_location = valobj_addr + ptr_size;
88 info_bits_location += 3;
92 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(
93 info_bits_location, 1, 0,
error);
97 bool is_mutable = (info_bits & 1) == 1;
98 bool is_inline = (info_bits & 0x60) == 0;
99 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
100 bool is_unicode = (info_bits & 0x10) == 0x10;
101 bool is_path_store = class_name ==
"NSPathStore2";
102 bool has_null = (info_bits & 8) == 8;
104 size_t explicit_length = 0;
105 if (!has_null && has_explicit_length && !is_path_store) {
107 if (is_mutable && !is_inline)
108 explicit_length_offset =
109 explicit_length_offset + ptr_size;
111 explicit_length = explicit_length + 0;
112 else if (!is_inline && !is_mutable)
113 explicit_length_offset =
114 explicit_length_offset + ptr_size;
116 explicit_length_offset = 0;
118 if (explicit_length_offset) {
119 explicit_length_offset = valobj_addr + explicit_length_offset;
120 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(
121 explicit_length_offset, 4, 0,
error);
125 const llvm::StringSet<> supported_string_classes = {
126 "NSString",
"CFMutableStringRef",
127 "CFStringRef",
"__NSCFConstantString",
128 "__NSCFString",
"NSCFConstantString",
129 "NSCFString",
"NSPathStore2"};
130 if (supported_string_classes.count(class_name) == 0) {
136 llvm::StringRef prefix, suffix;
138 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
145 uint64_t location = 2 * ptr_size + valobj_addr;
146 llvm::Expected<lldb::addr_t> location_or_err =
147 process_sp->ReadPointerFromMemory(location);
148 if (!location_or_err) {
149 llvm::consumeError(location_or_err.takeError());
152 location = *location_or_err;
153 if (has_explicit_length && is_unicode) {
164 StringPrinter::StringElementType::UTF16>(options);
175 StringPrinter::StringElementType::ASCII>(options);
177 }
else if (is_inline && has_explicit_length && !is_unicode &&
178 !is_path_store && !is_mutable) {
179 uint64_t location = 3 * ptr_size + valobj_addr;
190 StringPrinter::StringElementType::ASCII>(options);
191 }
else if (is_unicode) {
192 uint64_t location = valobj_addr + 2 * ptr_size;
194 if (!has_explicit_length) {
197 location += ptr_size;
199 llvm::Expected<lldb::addr_t> location_or_err =
200 process_sp->ReadPointerFromMemory(location);
201 if (!location_or_err) {
202 llvm::consumeError(location_or_err.takeError());
205 location = *location_or_err;
213 if (has_explicit_length)
220 StringPrinter::StringElementType::UTF16>(options);
221 }
else if (is_path_store) {
223 uint64_t length_ivar_offset = 1 * ptr_size;
229 if (!length_valobj_sp)
232 explicit_length = length_valobj_sp->GetValueAsUnsigned(0) >> 20;
241 if (has_explicit_length)
248 StringPrinter::StringElementType::UTF16>(options);
249 }
else if (is_inline) {
250 uint64_t location = valobj_addr + 2 * ptr_size;
251 if (!has_explicit_length) {
256 process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0,
error);
257 has_explicit_length = !(
error.Fail() || explicit_length == 0);
265 if (has_explicit_length)
271 if (has_explicit_length)
273 StringPrinter::StringElementType::UTF8>(options);
276 StringPrinter::StringElementType::ASCII>(options);
278 uint64_t location = valobj_addr + 2 * ptr_size;
279 llvm::Expected<lldb::addr_t> location_or_err =
280 process_sp->ReadPointerFromMemory(location);
281 if (!location_or_err) {
282 llvm::consumeError(location_or_err.takeError());
285 location = *location_or_err;
286 if (has_explicit_length && !has_null)
297 StringPrinter::StringElementType::ASCII>(options);
338 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
342 uint64_t len_bits = 0, data_bits = 0;
343 if (!descriptor->GetTaggedPointerInfo(&len_bits, &data_bits,
nullptr))
346 static const int g_MaxNonBitmaskedLen = 7;
347 static const int g_SixbitMaxLen = 9;
348 static const int g_fiveBitMaxLen = 11;
350 static const char *sixBitToCharLookup =
"eilotrm.apdnsIc ufkMShjTRxgC4013"
351 "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
353 if (len_bits > g_fiveBitMaxLen)
356 llvm::StringRef prefix, suffix;
358 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
363 if (len_bits <= g_MaxNonBitmaskedLen) {
365 stream.
Printf(
"\"%s\"", (
const char *)&data_bits);
372 uint8_t shift_offset = 0;
374 if (len_bits <= g_SixbitMaxLen) {
382 std::vector<uint8_t> bytes;
383 bytes.resize(len_bits);
384 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits) {
385 uint8_t packed = data_bits & bitmask;
386 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
390 stream.
Printf(
"\"%s\"", &bytes[0]);
"lldb/Target/ExecutionContext.h" A class that contains an execution context.