LLDB mainline
ObjCLanguage.cpp
Go to the documentation of this file.
1//===-- ObjCLanguage.cpp --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <mutex>
10
11#include "ObjCLanguage.h"
12
15#include "lldb/Core/Debugger.h"
20#include "lldb/Target/Target.h"
24
25#include "llvm/Support/Threading.h"
26
29
30#include "CF.h"
31#include "Cocoa.h"
32#include "CoreMedia.h"
33#include "NSDictionary.h"
34#include "NSSet.h"
35#include "NSString.h"
36
37using namespace lldb;
38using namespace lldb_private;
39using namespace lldb_private::formatters;
40
42
47
51
52// Static Functions
53
55 switch (language) {
57 return new ObjCLanguage();
58 default:
59 return nullptr;
60 }
61}
62
63std::optional<const ObjCLanguage::ObjCMethodName>
64ObjCLanguage::ObjCMethodName::Create(llvm::StringRef name, bool strict) {
65 if (name.empty())
66 return std::nullopt;
67
68 // Objective-C method minimum requirements:
69 // - If `strict` is true, must start with '-' or '+' (1 char)
70 // - Must be followed by '[' (1 char)
71 // - Must have at least one character for class name (1 char)
72 // - Must have a space between class name and method name (1 char)
73 // - Must have at least one character for method name (1 char)
74 // - Must be end with ']' (1 char)
75 // This means that the minimum size is 5 characters (6 if `strict`)
76 // e.g. [a a] (-[a a] or +[a a] if `strict`)
77
78 // We can check length and ending invariants first
79 if (name.size() < (5 + (strict ? 1 : 0)) || name.back() != ']')
80 return std::nullopt;
81
82 // Figure out type
84 if (name.starts_with("+["))
85 type = eTypeClassMethod;
86 else if (name.starts_with("-["))
88
89 // If there's no type and it's strict, this is invalid
90 if (strict && type == eTypeUnspecified)
91 return std::nullopt;
92
93 // If not strict and type unspecified, make sure we start with '['
94 if (type == eTypeUnspecified && name.front() != '[')
95 return std::nullopt;
96
97 // If we've gotten here, we're confident that this looks enough like an
98 // Objective-C method to treat it like one.
99 ObjCLanguage::ObjCMethodName method_name(name, type);
100 return method_name;
101}
102
104 llvm::StringRef full = m_full;
105 const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
106 const size_t paren_pos = full.find('(', class_start_pos);
107 // If there's a category we want to stop there
108 if (paren_pos != llvm::StringRef::npos)
109 return full.substr(class_start_pos, paren_pos - class_start_pos);
110
111 // Otherwise we find the space separating the class and method
112 const size_t space_pos = full.find(' ', class_start_pos);
113 return full.substr(class_start_pos, space_pos - class_start_pos);
114}
115
117 llvm::StringRef full = m_full;
118 const size_t class_start_pos = (full.front() == '[' ? 1 : 2);
119 const size_t space_pos = full.find(' ', class_start_pos);
120 return full.substr(class_start_pos, space_pos - class_start_pos);
121}
122
124 llvm::StringRef full = m_full;
125 const size_t space_pos = full.find(' ');
126 if (space_pos == llvm::StringRef::npos)
127 return llvm::StringRef();
128 const size_t closing_bracket = full.find(']', space_pos);
129 return full.substr(space_pos + 1, closing_bracket - space_pos - 1);
130}
131
133 llvm::StringRef full = m_full;
134 const size_t open_paren_pos = full.find('(');
135 const size_t close_paren_pos = full.find(')');
136
137 if (open_paren_pos == llvm::StringRef::npos ||
138 close_paren_pos == llvm::StringRef::npos)
139 return llvm::StringRef();
140
141 return full.substr(open_paren_pos + 1,
142 close_paren_pos - (open_paren_pos + 1));
143}
144
146 llvm::StringRef full = m_full;
147 const size_t open_paren_pos = full.find('(');
148 const size_t close_paren_pos = full.find(')');
149 if (open_paren_pos == llvm::StringRef::npos ||
150 close_paren_pos == llvm::StringRef::npos)
151 return std::string();
152
153 llvm::StringRef class_name = GetClassName();
154 llvm::StringRef selector_name = GetSelector();
155
156 // Compute the total size to avoid reallocations
157 // class name + selector name + '[' + ' ' + ']'
158 size_t total_size = class_name.size() + selector_name.size() + 3;
160 total_size++; // For + or -
161
162 std::string name_sans_category;
163 name_sans_category.reserve(total_size);
164
166 name_sans_category += '+';
167 else if (m_type == eTypeInstanceMethod)
168 name_sans_category += '-';
169
170 name_sans_category += '[';
171 name_sans_category.append(class_name.data(), class_name.size());
172 name_sans_category += ' ';
173 name_sans_category.append(selector_name.data(), selector_name.size());
174 name_sans_category += ']';
175
176 return name_sans_category;
177}
178
179std::vector<Language::MethodNameVariant>
180ObjCLanguage::GetMethodNameVariants(llvm::StringRef method_name) const {
181 std::vector<Language::MethodNameVariant> variant_names;
182 std::optional<const ObjCLanguage::ObjCMethodName> objc_method =
183 ObjCLanguage::ObjCMethodName::Create(method_name, false);
184 if (!objc_method)
185 return variant_names;
186
187 variant_names.emplace_back(objc_method->GetSelector().str(),
188 lldb::eFunctionNameTypeSelector);
189
190 const std::string name_sans_category =
191 objc_method->GetFullNameWithoutCategory();
192
193 if (objc_method->IsClassMethod() || objc_method->IsInstanceMethod()) {
194 if (!name_sans_category.empty())
195 variant_names.emplace_back(name_sans_category,
196 lldb::eFunctionNameTypeFull);
197 } else {
198 StreamString strm;
199
200 strm.Printf("+%s", objc_method->GetFullName().c_str());
201 variant_names.emplace_back(strm.GetString().str(),
202 lldb::eFunctionNameTypeFull);
203 strm.Clear();
204
205 strm.Printf("-%s", objc_method->GetFullName().c_str());
206 variant_names.emplace_back(strm.GetString().str(),
207 lldb::eFunctionNameTypeFull);
208 strm.Clear();
209
210 if (!name_sans_category.empty()) {
211 strm.Printf("+%s", name_sans_category.c_str());
212 variant_names.emplace_back(strm.GetString().str(),
213 lldb::eFunctionNameTypeFull);
214 strm.Clear();
215
216 strm.Printf("-%s", name_sans_category.c_str());
217 variant_names.emplace_back(strm.GetString().str(),
218 lldb::eFunctionNameTypeFull);
219 }
220 }
221
222 return variant_names;
223}
224
225std::pair<FunctionNameType, std::optional<ConstString>>
227 FunctionNameType func_name_type = eFunctionNameTypeNone;
228
230 func_name_type = eFunctionNameTypeFull;
231
233 func_name_type |= eFunctionNameTypeSelector;
234
235 return {func_name_type, std::nullopt};
236}
237
239 ConstString demangled_name = mangled.GetDemangledName();
240 if (!demangled_name)
241 return false;
242 return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
243}
244
245static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
246 if (!objc_category_sp)
247 return;
248
249 TypeSummaryImpl::Flags objc_flags;
250 objc_flags.SetCascades(false)
251 .SetSkipPointers(true)
252 .SetSkipReferences(true)
254 .SetDontShowValue(true)
256 .SetHideItemNames(false);
257
260 objc_category_sp->AddTypeSummary("BOOL", eFormatterMatchExact,
261 ObjC_BOOL_summary);
262 objc_category_sp->AddTypeSummary("BOOL &", eFormatterMatchExact,
263 ObjC_BOOL_summary);
264 objc_category_sp->AddTypeSummary("BOOL *", eFormatterMatchExact,
265 ObjC_BOOL_summary);
266
267 // we need to skip pointers here since we are special casing a SEL* when
268 // retrieving its value
269 objc_flags.SetSkipPointers(true);
270 AddCXXSummary(objc_category_sp,
272 "SEL summary provider", "SEL", objc_flags);
273 AddCXXSummary(objc_category_sp,
275 "SEL summary provider", "struct objc_selector", objc_flags);
276 AddCXXSummary(objc_category_sp,
278 "SEL summary provider", "objc_selector", objc_flags);
279 AddCXXSummary(objc_category_sp,
281 "SEL summary provider", "objc_selector *", objc_flags);
282 AddCXXSummary(objc_category_sp,
284 "SEL summary provider", "SEL *", objc_flags);
285
286 AddCXXSummary(objc_category_sp,
288 "Class summary provider", "Class", objc_flags);
289
290 SyntheticChildren::Flags class_synth_flags;
291 class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
292 false);
293
294 AddCXXSynthetic(objc_category_sp,
296 "Class synthetic children", "Class", class_synth_flags);
297
298 objc_flags.SetSkipPointers(false);
299 objc_flags.SetCascades(true);
300 objc_flags.SetSkipReferences(false);
301
302 AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
303 "__block_literal_generic", objc_flags);
304
305 AddStringSummary(objc_category_sp,
306 "${var.years} years, ${var.months} "
307 "months, ${var.days} days, ${var.hours} "
308 "hours, ${var.minutes} minutes "
309 "${var.seconds} seconds",
310 "CFGregorianUnits", objc_flags);
311 AddStringSummary(objc_category_sp,
312 "location=${var.location} length=${var.length}", "CFRange",
313 objc_flags);
314
315 AddStringSummary(objc_category_sp,
316 "location=${var.location}, length=${var.length}", "NSRange",
317 objc_flags);
318 AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
319 "NSRectArray", objc_flags);
320
321 AddOneLineSummary(objc_category_sp, "NSPoint", objc_flags);
322 AddOneLineSummary(objc_category_sp, "NSSize", objc_flags);
323 AddOneLineSummary(objc_category_sp, "NSRect", objc_flags);
324
325 AddOneLineSummary(objc_category_sp, "CGSize", objc_flags);
326 AddOneLineSummary(objc_category_sp, "CGPoint", objc_flags);
327 AddOneLineSummary(objc_category_sp, "CGRect", objc_flags);
328
329 AddStringSummary(objc_category_sp,
330 "red=${var.red} green=${var.green} blue=${var.blue}",
331 "RGBColor", objc_flags);
333 objc_category_sp,
334 "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", "Rect",
335 objc_flags);
336 AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}", "Point",
337 objc_flags);
338 AddStringSummary(objc_category_sp,
339 "${var.month}/${var.day}/${var.year} ${var.hour} "
340 ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
341 "DateTimeRect *", objc_flags);
342 AddStringSummary(objc_category_sp,
343 "${var.ld.month}/${var.ld.day}/"
344 "${var.ld.year} ${var.ld.hour} "
345 ":${var.ld.minute} :${var.ld.second} "
346 "dayOfWeek:${var.ld.dayOfWeek}",
347 "LongDateRect", objc_flags);
348 AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})", "HIPoint",
349 objc_flags);
350 AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
351 "HIRect", objc_flags);
352
353 TypeSummaryImpl::Flags appkit_flags;
354 appkit_flags.SetCascades(true)
355 .SetSkipPointers(false)
356 .SetSkipReferences(false)
358 .SetDontShowValue(false)
360 .SetHideItemNames(false);
361
362 appkit_flags.SetDontShowChildren(false);
363
364 AddCXXSummary(objc_category_sp,
366 "NSArray summary provider", "NSArray", appkit_flags);
367 AddCXXSummary(objc_category_sp,
369 "NSArray summary provider", "NSConstantArray", appkit_flags);
370 AddCXXSummary(objc_category_sp,
372 "NSArray summary provider", "NSMutableArray", appkit_flags);
373 AddCXXSummary(objc_category_sp,
375 "NSArray summary provider", "__NSArrayI", appkit_flags);
376 AddCXXSummary(objc_category_sp,
378 "NSArray summary provider", "__NSArray0", appkit_flags);
381 "NSArray summary provider", "__NSSingleObjectArrayI", appkit_flags);
382 AddCXXSummary(objc_category_sp,
384 "NSArray summary provider", "__NSArrayM", appkit_flags);
385 AddCXXSummary(objc_category_sp,
387 "NSArray summary provider", "__NSCFArray", appkit_flags);
388 AddCXXSummary(objc_category_sp,
390 "NSArray summary provider", "_NSCallStackArray", appkit_flags);
391 AddCXXSummary(objc_category_sp,
393 "NSArray summary provider", "CFArrayRef", appkit_flags);
394 AddCXXSummary(objc_category_sp,
396 "NSArray summary provider", "CFMutableArrayRef", appkit_flags);
397
398 AddCXXSummary(objc_category_sp,
400 "NSDictionary summary provider", "NSDictionary", appkit_flags);
401 AddCXXSummary(objc_category_sp,
403 "NSDictionary summary provider", "NSConstantDictionary",
404 appkit_flags);
405 AddCXXSummary(objc_category_sp,
407 "NSDictionary summary provider", "NSMutableDictionary",
408 appkit_flags);
409 AddCXXSummary(objc_category_sp,
411 "NSDictionary summary provider", "__NSCFDictionary",
412 appkit_flags);
413 AddCXXSummary(objc_category_sp,
415 "NSDictionary summary provider", "__NSDictionaryI",
416 appkit_flags);
417 AddCXXSummary(objc_category_sp,
419 "NSDictionary summary provider", "__NSSingleEntryDictionaryI",
420 appkit_flags);
421 AddCXXSummary(objc_category_sp,
423 "NSDictionary summary provider", "__NSDictionaryM",
424 appkit_flags);
425 AddCXXSummary(objc_category_sp,
427 "NSDictionary summary provider", "CFDictionaryRef",
428 appkit_flags);
429 AddCXXSummary(objc_category_sp,
431 "NSDictionary summary provider", "__CFDictionary",
432 appkit_flags);
433 AddCXXSummary(objc_category_sp,
435 "NSDictionary summary provider", "CFMutableDictionaryRef",
436 appkit_flags);
437
438 AddCXXSummary(objc_category_sp,
440 "NSSet summary", "NSSet", appkit_flags);
441 AddCXXSummary(objc_category_sp,
443 "NSMutableSet summary", "NSMutableSet", appkit_flags);
444 AddCXXSummary(objc_category_sp,
446 "CFSetRef summary", "CFSetRef", appkit_flags);
447 AddCXXSummary(objc_category_sp,
449 "CFMutableSetRef summary", "CFMutableSetRef", appkit_flags);
450 AddCXXSummary(objc_category_sp,
452 "__NSCFSet summary", "__NSCFSet", appkit_flags);
453 AddCXXSummary(objc_category_sp,
455 "__CFSet summary", "__CFSet", appkit_flags);
456 AddCXXSummary(objc_category_sp,
458 "__NSSetI summary", "__NSSetI", appkit_flags);
459 AddCXXSummary(objc_category_sp,
461 "__NSSetM summary", "__NSSetM", appkit_flags);
462 AddCXXSummary(objc_category_sp,
464 "NSCountedSet summary", "NSCountedSet", appkit_flags);
465 AddCXXSummary(objc_category_sp,
467 "NSMutableSet summary", "NSMutableSet", appkit_flags);
468 AddCXXSummary(objc_category_sp,
470 "NSOrderedSet summary", "NSOrderedSet", appkit_flags);
471 AddCXXSummary(objc_category_sp,
473 "__NSOrderedSetI summary", "__NSOrderedSetI", appkit_flags);
474 AddCXXSummary(objc_category_sp,
476 "__NSOrderedSetM summary", "__NSOrderedSetM", appkit_flags);
477
478 AddCXXSummary(objc_category_sp,
480 "NSError summary provider", "NSError", appkit_flags);
481 AddCXXSummary(objc_category_sp,
483 "NSException summary provider", "NSException", appkit_flags);
484
485 // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
486 // ConstString("$_lldb_typegen_nspair"), appkit_flags);
487
488 appkit_flags.SetDontShowChildren(true);
489
490 AddCXXSynthetic(objc_category_sp,
492 "NSArray synthetic children", "__NSArrayM",
494 AddCXXSynthetic(objc_category_sp,
496 "NSArray synthetic children", "__NSArrayI",
498 AddCXXSynthetic(objc_category_sp,
500 "NSArray synthetic children", "__NSArray0",
502 AddCXXSynthetic(objc_category_sp,
504 "NSArray synthetic children", "__NSSingleObjectArrayI",
506 AddCXXSynthetic(objc_category_sp,
508 "NSArray synthetic children", "NSArray",
510 AddCXXSynthetic(objc_category_sp,
512 "NSArray synthetic children", "NSConstantArray",
514 AddCXXSynthetic(objc_category_sp,
516 "NSArray synthetic children", "NSMutableArray",
518 AddCXXSynthetic(objc_category_sp,
520 "NSArray synthetic children", "__NSCFArray",
522 AddCXXSynthetic(objc_category_sp,
524 "NSArray synthetic children", "_NSCallStackArray",
526 AddCXXSynthetic(objc_category_sp,
528 "NSArray synthetic children", "CFMutableArrayRef",
530 AddCXXSynthetic(objc_category_sp,
532 "NSArray synthetic children", "CFArrayRef",
534
536 objc_category_sp,
538 "NSDictionary synthetic children", "__NSDictionaryM",
541 objc_category_sp,
543 "NSDictionary synthetic children", "NSConstantDictionary",
546 objc_category_sp,
548 "NSDictionary synthetic children", "__NSDictionaryI",
551 objc_category_sp,
553 "NSDictionary synthetic children", "__NSSingleEntryDictionaryI",
556 objc_category_sp,
558 "NSDictionary synthetic children", "__NSCFDictionary",
561 objc_category_sp,
563 "NSDictionary synthetic children", "NSDictionary",
566 objc_category_sp,
568 "NSDictionary synthetic children", "NSMutableDictionary",
571 objc_category_sp,
573 "NSDictionary synthetic children", "CFDictionaryRef",
576 objc_category_sp,
578 "NSDictionary synthetic children", "CFMutableDictionaryRef",
581 objc_category_sp,
583 "NSDictionary synthetic children", "__CFDictionary",
585
586 AddCXXSynthetic(objc_category_sp,
588 "NSError synthetic children", "NSError",
590 AddCXXSynthetic(objc_category_sp,
592 "NSException synthetic children", "NSException",
594
597 "NSSet synthetic children", "NSSet", ScriptedSyntheticChildren::Flags());
598 AddCXXSynthetic(objc_category_sp,
600 "__NSSetI synthetic children", "__NSSetI",
602 AddCXXSynthetic(objc_category_sp,
604 "__NSSetM synthetic children", "__NSSetM",
606 AddCXXSynthetic(objc_category_sp,
608 "__NSCFSet synthetic children", "__NSCFSet",
610 AddCXXSynthetic(objc_category_sp,
612 "CFSetRef synthetic children", "CFSetRef",
614
615 AddCXXSynthetic(objc_category_sp,
617 "NSMutableSet synthetic children", "NSMutableSet",
619 AddCXXSynthetic(objc_category_sp,
621 "NSOrderedSet synthetic children", "NSOrderedSet",
623 AddCXXSynthetic(objc_category_sp,
625 "__NSOrderedSetI synthetic children", "__NSOrderedSetI",
627 AddCXXSynthetic(objc_category_sp,
629 "__NSOrderedSetM synthetic children", "__NSOrderedSetM",
631 AddCXXSynthetic(objc_category_sp,
633 "__CFSet synthetic children", "__CFSet",
635
636 AddCXXSynthetic(objc_category_sp,
638 "NSIndexPath synthetic children", "NSIndexPath",
640
641 AddCXXSummary(objc_category_sp,
643 "CFBag summary provider", "CFBagRef", appkit_flags);
644 AddCXXSummary(objc_category_sp,
646 "CFBag summary provider", "__CFBag", appkit_flags);
647 AddCXXSummary(objc_category_sp,
649 "CFBag summary provider", "const struct __CFBag", appkit_flags);
650 AddCXXSummary(objc_category_sp,
652 "CFBag summary provider", "CFMutableBagRef", appkit_flags);
653
656 "CFBinaryHeap summary provider", "CFBinaryHeapRef", appkit_flags);
659 "CFBinaryHeap summary provider", "__CFBinaryHeap", appkit_flags);
660
661 AddCXXSummary(objc_category_sp,
663 "NSString summary provider", "NSString", appkit_flags);
664 AddCXXSummary(objc_category_sp,
666 "NSString summary provider", "CFStringRef", appkit_flags);
667 AddCXXSummary(objc_category_sp,
669 "NSString summary provider", "__CFString", appkit_flags);
672 "NSString summary provider", "CFMutableStringRef", appkit_flags);
673 AddCXXSummary(objc_category_sp,
675 "NSString summary provider", "NSMutableString", appkit_flags);
678 "NSString summary provider", "__NSCFConstantString", appkit_flags);
679 AddCXXSummary(objc_category_sp,
681 "NSString summary provider", "__NSCFString", appkit_flags);
684 "NSString summary provider", "NSCFConstantString", appkit_flags);
685 AddCXXSummary(objc_category_sp,
687 "NSString summary provider", "NSCFString", appkit_flags);
688 AddCXXSummary(objc_category_sp,
690 "NSString summary provider", "NSPathStore2", appkit_flags);
693 "NSString summary provider", "NSTaggedPointerString", appkit_flags);
694 AddCXXSummary(objc_category_sp,
696 "NSString summary provider", "NSIndirectTaggedPointerString",
697 appkit_flags);
698
699 AddCXXSummary(objc_category_sp,
701 "NSAttributedString summary provider", "NSAttributedString",
702 appkit_flags);
704 objc_category_sp,
706 "NSMutableAttributedString summary provider", "NSMutableAttributedString",
707 appkit_flags);
709 objc_category_sp,
711 "NSMutableAttributedString summary provider",
712 "NSConcreteMutableAttributedString", appkit_flags);
713
714 AddCXXSummary(objc_category_sp,
716 "NSBundle summary provider", "NSBundle", appkit_flags);
717
718 AddCXXSummary(objc_category_sp,
720 "NSData summary provider", "NSData", appkit_flags);
721 AddCXXSummary(objc_category_sp,
723 "NSData summary provider", "_NSInlineData", appkit_flags);
724 AddCXXSummary(objc_category_sp,
726 "NSData summary provider", "NSConcreteData", appkit_flags);
729 "NSData summary provider", "NSConcreteMutableData", appkit_flags);
730 AddCXXSummary(objc_category_sp,
732 "NSData summary provider", "NSMutableData", appkit_flags);
733 AddCXXSummary(objc_category_sp,
735 "NSData summary provider", "__NSCFData", appkit_flags);
736 AddCXXSummary(objc_category_sp,
738 "NSData summary provider", "CFDataRef", appkit_flags);
739 AddCXXSummary(objc_category_sp,
741 "NSData summary provider", "CFMutableDataRef", appkit_flags);
742
743 AddCXXSummary(objc_category_sp,
745 "NSMachPort summary provider", "NSMachPort", appkit_flags);
746
749 "NSNotification summary provider", "NSNotification", appkit_flags);
750 AddCXXSummary(objc_category_sp,
752 "NSNotification summary provider", "NSConcreteNotification",
753 appkit_flags);
754
755 AddCXXSummary(objc_category_sp,
757 "NSNumber summary provider", "NSNumber", appkit_flags);
760 "NSNumber summary provider", "NSConstantIntegerNumber", appkit_flags);
763 "NSNumber summary provider", "NSConstantDoubleNumber", appkit_flags);
766 "NSNumber summary provider", "NSConstantFloatNumber", appkit_flags);
767 AddCXXSummary(objc_category_sp,
769 "CFNumberRef summary provider", "CFNumberRef", appkit_flags);
770 AddCXXSummary(objc_category_sp,
772 "NSNumber summary provider", "__NSCFBoolean", appkit_flags);
773 AddCXXSummary(objc_category_sp,
775 "NSNumber summary provider", "__NSCFNumber", appkit_flags);
776 AddCXXSummary(objc_category_sp,
778 "NSNumber summary provider", "NSCFBoolean", appkit_flags);
779 AddCXXSummary(objc_category_sp,
781 "NSNumber summary provider", "NSCFNumber", appkit_flags);
784 "NSDecimalNumber summary provider", "NSDecimalNumber", appkit_flags);
785
786 AddCXXSummary(objc_category_sp,
788 "NSURL summary provider", "NSURL", appkit_flags);
789 AddCXXSummary(objc_category_sp,
791 "NSURL summary provider", "CFURLRef", appkit_flags);
792
793 AddCXXSummary(objc_category_sp,
795 "NSDate summary provider", "NSDate", appkit_flags);
796 AddCXXSummary(objc_category_sp,
798 "NSDate summary provider", "__NSDate", appkit_flags);
799 AddCXXSummary(objc_category_sp,
801 "NSDate summary provider", "__NSTaggedDate", appkit_flags);
802 AddCXXSummary(objc_category_sp,
804 "NSDate summary provider", "NSCalendarDate", appkit_flags);
805
806 AddCXXSummary(objc_category_sp,
808 "NSTimeZone summary provider", "NSTimeZone", appkit_flags);
809 AddCXXSummary(objc_category_sp,
811 "NSTimeZone summary provider", "CFTimeZoneRef", appkit_flags);
812 AddCXXSummary(objc_category_sp,
814 "NSTimeZone summary provider", "__NSTimeZone", appkit_flags);
815
816 // CFAbsoluteTime is actually a double rather than a pointer to an object we
817 // do not care about the numeric value, since it is probably meaningless to
818 // users
819 appkit_flags.SetDontShowValue(true);
822 "CFAbsoluteTime summary provider", "CFAbsoluteTime", appkit_flags);
823 appkit_flags.SetDontShowValue(false);
824
825 AddCXXSummary(objc_category_sp,
827 "NSIndexSet summary provider", "NSIndexSet", appkit_flags);
830 "NSIndexSet summary provider", "NSMutableIndexSet", appkit_flags);
831
832 AddStringSummary(objc_category_sp,
833 "@\"${var.month%d}/${var.day%d}/${var.year%d} "
834 "${var.hour%d}:${var.minute%d}:${var.second}\"",
835 "CFGregorianDate", appkit_flags);
836
837 AddCXXSummary(objc_category_sp,
839 "CFBitVector summary provider", "CFBitVectorRef", appkit_flags);
842 "CFBitVector summary provider", "CFMutableBitVectorRef", appkit_flags);
843 AddCXXSummary(objc_category_sp,
845 "CFBitVector summary provider", "__CFBitVector", appkit_flags);
848 "CFBitVector summary provider", "__CFMutableBitVector", appkit_flags);
849}
850
851static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
852 if (!objc_category_sp)
853 return;
854
855 TypeSummaryImpl::Flags cm_flags;
856 cm_flags.SetCascades(true)
857 .SetDontShowChildren(false)
858 .SetDontShowValue(false)
859 .SetHideItemNames(false)
861 .SetSkipPointers(false)
862 .SetSkipReferences(false);
863
864 AddCXXSummary(objc_category_sp,
866 "CMTime summary provider", "CMTime", cm_flags);
867}
868
870 static llvm::once_flag g_initialize;
871 static TypeCategoryImplSP g_category;
872
873 llvm::call_once(g_initialize, [this]() -> void {
875 g_category);
876 if (g_category) {
877 LoadCoreMediaFormatters(g_category);
878 LoadObjCFormatters(g_category);
879 }
880 });
881 return g_category;
882}
883
886 static llvm::once_flag g_initialize;
888
889 llvm::call_once(g_initialize, []() -> void {
890 // An Objective-C tagged pointer (e.g. a single-index NSIndexSet
891 // or a small NSNumber) packs its whole state into the pointer
892 // bits and has no object in memory. Since its declared base
893 // classes and ivars cannot be read, this synthtic child provider
894 // hides them. Other synthetic child providers take precedence of
895 // this.
896 g_formatters.push_back(
899 static CXXSyntheticChildren::SharedPointer formatter_sp(
902 .SetCascades(true)
903 .SetSkipPointers(false)
904 .SetSkipReferences(false)
905 .SetNonCacheable(true),
906 "tagged pointer synthetic children",
908
909 ProcessSP process_sp = valobj.GetProcessSP();
910 if (!process_sp)
911 return nullptr;
912 if (ObjCLanguageRuntime *runtime =
913 ObjCLanguageRuntime::Get(*process_sp))
914 if (runtime->IsTaggedPointerValue(valobj))
915 return formatter_sp;
916 return nullptr;
917 });
918 });
919
920 return g_formatters;
921}
922
923std::vector<FormattersMatchCandidate>
925 lldb::DynamicValueType use_dynamic) {
926 std::vector<FormattersMatchCandidate> result;
927
928 if (use_dynamic == lldb::eNoDynamicValues)
929 return result;
930
931 CompilerType compiler_type(valobj.GetCompilerType());
932
933 const bool check_cpp = false;
934 const bool check_objc = true;
935 bool canBeObjCDynamic =
936 compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
937
938 if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
939 do {
940 lldb::ProcessSP process_sp = valobj.GetProcessSP();
941 if (!process_sp)
942 break;
943 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
944 if (runtime == nullptr)
945 break;
947 runtime->GetClassDescriptor(valobj));
948 if (!objc_class_sp)
949 break;
950 if (ConstString name = objc_class_sp->GetClassName())
951 result.push_back(
952 {name, valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(),
953 TypeImpl(objc_class_sp->GetType()),
955 } while (false);
956 }
957
958 return result;
959}
960
961std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
962 class ObjCScavengerResult : public Language::TypeScavenger::Result {
963 public:
964 ObjCScavengerResult(CompilerType type)
965 : Language::TypeScavenger::Result(), m_compiler_type(type) {}
966
967 bool IsValid() override { return m_compiler_type.IsValid(); }
968
969 bool DumpToStream(Stream &stream, bool print_help_if_available) override {
970 if (IsValid()) {
971 m_compiler_type.DumpTypeDescription(&stream);
972 stream.EOL();
973 return true;
974 }
975 return false;
976 }
977
978 private:
979 CompilerType m_compiler_type;
980 };
981
982 class ObjCRuntimeScavenger : public Language::TypeScavenger {
983 protected:
984 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
985 ResultSet &results) override {
986 bool result = false;
987
988 if (auto *process = exe_scope->CalculateProcess().get()) {
989 if (auto *objc_runtime = ObjCLanguageRuntime::Get(*process)) {
990 if (auto *decl_vendor = objc_runtime->GetDeclVendor()) {
991 ConstString name(key);
992 for (const CompilerType &type :
993 decl_vendor->FindTypes(name, /*max_matches*/ UINT32_MAX)) {
994 result = true;
995 std::unique_ptr<Language::TypeScavenger::Result> result(
996 new ObjCScavengerResult(type));
997 results.insert(std::move(result));
998 }
999 }
1000 }
1001 }
1002
1003 return result;
1004 }
1005
1006 friend class lldb_private::ObjCLanguage;
1007 };
1008
1009 class ObjCModulesScavenger : public Language::TypeScavenger {
1010 protected:
1011 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
1012 ResultSet &results) override {
1013 bool result = false;
1014
1015 if (auto *target = exe_scope->CalculateTarget().get()) {
1016 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
1017 target->GetPersistentExpressionStateForLanguage(
1019 if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
1020 persistent_vars->GetClangModulesDeclVendor()) {
1021 ConstString key_cs(key);
1022 auto types = clang_modules_decl_vendor->FindTypes(
1023 key_cs, /*max_matches*/ UINT32_MAX);
1024 if (!types.empty()) {
1025 result = true;
1026 std::unique_ptr<Language::TypeScavenger::Result> result(
1027 new ObjCScavengerResult(types.front()));
1028 results.insert(std::move(result));
1029 }
1030 }
1031 }
1032
1033 return result;
1034 }
1035
1036 friend class lldb_private::ObjCLanguage;
1037 };
1038
1039 class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
1040 public:
1041 CompilerType AdjustForInclusion(CompilerType &candidate) override {
1042 LanguageType lang_type(candidate.GetMinimumLanguage());
1043 if (!Language::LanguageIsObjC(lang_type))
1044 return CompilerType();
1045 if (candidate.IsTypedefType())
1046 return candidate.GetTypedefedType();
1047 return candidate;
1048 }
1049 };
1050
1051 return std::unique_ptr<TypeScavenger>(
1052 new Language::EitherTypeScavenger<ObjCModulesScavenger,
1053 ObjCRuntimeScavenger,
1054 ObjCDebugInfoScavenger>());
1055}
1056
1057std::pair<llvm::StringRef, llvm::StringRef>
1058ObjCLanguage::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {
1059 static constexpr llvm::StringRef empty;
1060 static const llvm::StringMap<
1061 std::pair<const llvm::StringRef, const llvm::StringRef>>
1062 g_affix_map = {
1063 {"CFBag", {"@", empty}},
1064 {"CFBinaryHeap", {"@", empty}},
1065 {"NSString", {"@", empty}},
1066 {"NSString*", {"@", empty}},
1067 {"NSNumber:char", {"(char)", empty}},
1068 {"NSNumber:short", {"(short)", empty}},
1069 {"NSNumber:int", {"(int)", empty}},
1070 {"NSNumber:long", {"(long)", empty}},
1071 {"NSNumber:int128_t", {"(int128_t)", empty}},
1072 {"NSNumber:float", {"(float)", empty}},
1073 {"NSNumber:double", {"(double)", empty}},
1074 {"NSData", {"@\"", "\""}},
1075 {"NSArray", {"@\"", "\""}},
1076 };
1077 return g_affix_map.lookup(type_hint);
1078}
1079
1081 const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1082 bool isObjCpointer =
1083 (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1084 if (!isObjCpointer)
1085 return false;
1086 bool canReadValue = true;
1087 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1088 return canReadValue && isZero;
1089}
1090
1091bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
1092 const auto suffixes = {".h", ".m", ".M"};
1093 for (auto suffix : suffixes) {
1094 if (file_path.ends_with_insensitive(suffix))
1095 return true;
1096 }
1097 return false;
1098}
1099
1100std::optional<bool>
1101ObjCLanguage::GetBooleanFromString(llvm::StringRef str) const {
1102 return llvm::StringSwitch<std::optional<bool>>(str)
1103 .Case("YES", {true})
1104 .Case("NO", {false})
1105 .Default({});
1106}
1107
1108bool ObjCLanguage::IsPossibleObjCMethodName(llvm::StringRef name) {
1109 if (!name.starts_with("-[") && !name.starts_with("+["))
1110 return false;
1111
1112 return name.ends_with("]");
1113}
static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
#define LLDB_PLUGIN_DEFINE(PluginName)
Generic representation of a type in a programming language.
lldb::LanguageType GetMinimumLanguage()
bool IsPossibleDynamicType(CompilerType *target_type, bool check_cplusplus, bool check_objc) const
CompilerType GetTypedefedType() const
If the current object represents a typedef type, get the underlying type.
A uniqued constant string class.
Definition ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
static bool GetCategory(ConstString category, lldb::TypeCategoryImplSP &entry, bool allow_create=true)
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual lldb::ProcessSP CalculateProcess()=0
virtual lldb::TargetSP CalculateTarget()=0
HardcodedFormatterFinders< SyntheticChildren > HardcodedSyntheticFinder
static bool LanguageIsObjC(lldb::LanguageType language)
Definition Language.cpp:357
A class that handles mangled names.
Definition Mangled.h:34
ConstString GetDemangledName() const
Demangled name get accessor.
Definition Mangled.cpp:284
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
llvm::StringRef GetClassNameWithCategory() const
Returns a reference to the class name with the category.
llvm::StringRef GetSelector() const
Returns a reference to the selector name.
static std::optional< const ObjCMethodName > Create(llvm::StringRef name, bool strict)
The static factory method for creating a ObjCMethodName.
llvm::StringRef GetCategory() const
Returns a reference to the category name.
llvm::StringRef GetClassName() const
Returns a reference to the class name.
std::string GetFullNameWithoutCategory() const
Creates a variation of this method without the category.
llvm::StringRef GetPluginName() override
std::pair< llvm::StringRef, llvm::StringRef > GetFormatterPrefixSuffix(llvm::StringRef type_hint) override
An individual data formatter may apply to several types and cross language boundaries.
static bool IsPossibleObjCSelector(const char *name)
static lldb_private::Language * CreateInstance(lldb::LanguageType language)
std::unique_ptr< TypeScavenger > GetTypeScavenger() override
lldb::TypeCategoryImplSP GetFormatters() override
std::pair< lldb::FunctionNameType, std::optional< ConstString > > GetFunctionNameInfo(ConstString name) const override
bool SymbolNameFitsToLanguage(const Mangled &mangled) const override
Returns true iff the given symbol name is compatible with the mangling scheme of this language.
bool IsSourceFile(llvm::StringRef file_path) const override
static bool IsPossibleObjCMethodName(llvm::StringRef name)
virtual std::optional< bool > GetBooleanFromString(llvm::StringRef str) const override
static llvm::StringRef GetPluginNameStatic()
std::vector< FormattersMatchCandidate > GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) override
HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics() override
bool IsNilReference(ValueObject &valobj) override
std::vector< Language::MethodNameVariant > GetMethodNameVariants(llvm::StringRef method_name) const override
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
Flags & SetSkipReferences(bool value=true)
Flags & SetSkipPointers(bool value=true)
Flags & SetCascades(bool value=true)
std::shared_ptr< SyntheticChildren > SharedPointer
Flags & SetCascades(bool value=true)
Definition TypeSummary.h:93
Flags & SetSkipPointers(bool value=true)
Flags & SetHideItemNames(bool value=true)
Flags & SetDontShowChildren(bool value=true)
Flags & SetSkipReferences(bool value=true)
Flags & SetShowMembersOneLiner(bool value=true)
Flags & SetDontShowValue(bool value=true)
lldb::ProcessSP GetProcessSP() const
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
lldb::TargetSP GetTargetSP() const
CompilerType GetCompilerType()
#define UINT32_MAX
bool NSMutableAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSString.cpp:316
void AddOneLineSummary(TypeCategoryImpl::SharedPointer category_sp, llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex=false)
bool NSURLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:778
bool CMTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CoreMedia.cpp:22
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:44
SyntheticChildrenFrontEnd * NSArraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool ObjCBOOLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1127
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:231
bool NSBundleSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:38
bool NSIndexSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:233
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:28
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
void AddCXXSummary(TypeCategoryImpl::SharedPointer category_sp, CXXFunctionSummaryFormat::Callback funct, const char *description, llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex=false)
Add a summary that is implemented by a C++ callback.
bool NSAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSString.cpp:287
bool NSArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSArray.cpp:325
bool NSSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSSet.cpp:220
void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char *string, llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex=false)
bool NSDictionarySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
SyntheticChildrenFrontEnd * NSSetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool NSDataSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1064
void AddCXXSynthetic(TypeCategoryImpl::SharedPointer category_sp, CXXSyntheticChildren::CreateFrontEndCallback generator, const char *description, llvm::StringRef type_name, ScriptedSyntheticChildren::Flags flags, bool regex=false)
Add a synthetic that is implemented by a C++ callback.
bool NSDateSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:902
SyntheticChildrenFrontEnd * NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:138
bool NSMachPortSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:187
bool NSError_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSError.cpp:52
bool ObjCSELSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1188
bool ObjCClassSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:1004
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:436
bool NSTimeZoneSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition Cocoa.cpp:89
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition NSString.cpp:33
SyntheticChildrenFrontEnd * NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
SyntheticChildrenFrontEnd * ObjCClassSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition CF.cpp:105
SyntheticChildrenFrontEnd * NSErrorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
LanguageType
Programming language type.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
static bool IsClangType(const CompilerType &ct)
Definition ClangUtil.cpp:17