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) {
158 StringPrinter::StringElementType::UTF16>(options);
169 StringPrinter::StringElementType::ASCII>(options);
171 }
else if (is_inline && has_explicit_length && !is_unicode &&
172 !is_path_store && !is_mutable) {
173 uint64_t location = 3 * ptr_size + valobj_addr;
184 StringPrinter::StringElementType::ASCII>(options);
185 }
else if (is_unicode) {
186 uint64_t location = valobj_addr + 2 * ptr_size;
188 if (!has_explicit_length) {
191 location += ptr_size;
193 location = process_sp->ReadPointerFromMemory(location,
error);
203 if (has_explicit_length)
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;
231 if (has_explicit_length)
238 StringPrinter::StringElementType::UTF16>(options);
239 }
else if (is_inline) {
240 uint64_t location = valobj_addr + 2 * ptr_size;
241 if (!has_explicit_length) {
246 process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0,
error);
247 has_explicit_length = !(
error.Fail() || explicit_length == 0);
255 if (has_explicit_length)
261 if (has_explicit_length)
263 StringPrinter::StringElementType::UTF8>(options);
266 StringPrinter::StringElementType::ASCII>(options);
268 uint64_t location = valobj_addr + 2 * ptr_size;
269 location = process_sp->ReadPointerFromMemory(location,
error);
272 if (has_explicit_length && !has_null)
283 StringPrinter::StringElementType::ASCII>(options);
324 static constexpr llvm::StringLiteral g_TypeHint(
"NSString");
328 uint64_t len_bits = 0, data_bits = 0;
329 if (!descriptor->GetTaggedPointerInfo(&len_bits, &data_bits,
nullptr))
332 static const int g_MaxNonBitmaskedLen = 7;
333 static const int g_SixbitMaxLen = 9;
334 static const int g_fiveBitMaxLen = 11;
336 static const char *sixBitToCharLookup =
"eilotrm.apdnsIc ufkMShjTRxgC4013"
337 "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
339 if (len_bits > g_fiveBitMaxLen)
342 llvm::StringRef prefix, suffix;
344 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
349 if (len_bits <= g_MaxNonBitmaskedLen) {
351 stream.
Printf(
"\"%s\"", (
const char *)&data_bits);
358 uint8_t shift_offset = 0;
360 if (len_bits <= g_SixbitMaxLen) {
368 std::vector<uint8_t> bytes;
369 bytes.resize(len_bits);
370 for (; len_bits > 0; data_bits >>= shift_offset, --len_bits) {
371 uint8_t packed = data_bits & bitmask;
372 bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
376 stream.
Printf(
"\"%s\"", &bytes[0]);
387 uint64_t payload = 0;
388 if (!descriptor->GetTaggedPointerInfo(
nullptr,
nullptr, &payload))
392 addr_t ptr = payload & 0x7fffffffffffULL;
394 size_t size = (payload >> 47) & 0x1fff;
397 std::vector<char> buf(size);
399 if (process_sp->ReadMemory(ptr, buf.data(), size, status)) {
400 llvm::StringRef prefix, suffix;
402 std::tie(prefix, suffix) =
403 language->GetFormatterPrefixSuffix(
"NSString");
404 stream << prefix <<
'"';
406 stream <<
'"' << suffix;
411 stream.
Format(
"<{0}>", status);
"lldb/Target/ExecutionContext.h" A class that contains an execution context.