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"
21#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
43void ObjCLanguage::Initialize() {
44 PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language",
45 CreateInstance);
46}
47
50}
51
52// Static Functions
53
55 switch (language) {
57 return new ObjCLanguage();
58 default:
59 return nullptr;
60 }
61}
62
64 m_full.Clear();
65 m_class.Clear();
69 m_category_is_valid = false;
70}
71
72bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
73 Clear();
74 if (name.empty())
75 return IsValid(strict);
76
77 // If "strict" is true. then the method must be specified with a '+' or '-'
78 // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
79 bool valid_prefix = false;
80
81 if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
82 valid_prefix = name[1] == '[';
83 if (name[0] == '+')
84 m_type = eTypeClassMethod;
85 else
86 m_type = eTypeInstanceMethod;
87 } else if (!strict) {
88 // "strict" is false, the name just needs to start with '['
89 valid_prefix = name[0] == '[';
90 }
91
92 if (valid_prefix) {
93 int name_len = name.size();
94 // Objective-C methods must have at least:
95 // "-[" or "+[" prefix
96 // One character for a class name
97 // One character for the space between the class name
98 // One character for the method name
99 // "]" suffix
100 if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') {
101 m_full.SetString(name);
102 }
103 }
104 return IsValid(strict);
105}
106
107bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) {
108 return SetName(llvm::StringRef(name), strict);
109}
110
112 if (!m_class) {
113 if (IsValid(false)) {
114 const char *full = m_full.GetCString();
115 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
116 const char *paren_pos = strchr(class_start, '(');
117 if (paren_pos) {
118 m_class.SetCStringWithLength(class_start, paren_pos - class_start);
119 } else {
120 // No '(' was found in the full name, we can definitively say that our
121 // category was valid (and empty).
122 m_category_is_valid = true;
123 const char *space_pos = strchr(full, ' ');
124 if (space_pos) {
125 m_class.SetCStringWithLength(class_start, space_pos - class_start);
126 if (!m_class_category) {
127 // No category in name, so we can also fill in the m_class_category
128 m_class_category = m_class;
129 }
130 }
131 }
132 }
133 }
134 return m_class;
135}
136
138 if (!m_class_category) {
139 if (IsValid(false)) {
140 const char *full = m_full.GetCString();
141 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
142 const char *space_pos = strchr(full, ' ');
143 if (space_pos) {
144 m_class_category.SetCStringWithLength(class_start,
145 space_pos - class_start);
146 // If m_class hasn't been filled in and the class with category doesn't
147 // contain a '(', then we can also fill in the m_class
148 if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) {
149 m_class = m_class_category;
150 // No '(' was found in the full name, we can definitively say that
151 // our category was valid (and empty).
152 m_category_is_valid = true;
153 }
154 }
155 }
156 }
157 return m_class_category;
158}
159
161 if (!m_selector) {
162 if (IsValid(false)) {
163 const char *full = m_full.GetCString();
164 const char *space_pos = strchr(full, ' ');
165 if (space_pos) {
166 ++space_pos; // skip the space
167 m_selector.SetCStringWithLength(space_pos, m_full.GetLength() -
168 (space_pos - full) - 1);
169 }
170 }
171 }
172 return m_selector;
173}
174
176 if (!m_category_is_valid && !m_category) {
177 if (IsValid(false)) {
178 m_category_is_valid = true;
179 const char *full = m_full.GetCString();
180 const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
181 const char *open_paren_pos = strchr(class_start, '(');
182 if (open_paren_pos) {
183 ++open_paren_pos; // Skip the open paren
184 const char *close_paren_pos = strchr(open_paren_pos, ')');
185 if (close_paren_pos)
186 m_category.SetCStringWithLength(open_paren_pos,
187 close_paren_pos - open_paren_pos);
188 }
189 }
190 }
191 return m_category;
192}
193
195 bool empty_if_no_category) {
196 if (IsValid(false)) {
197 if (HasCategory()) {
198 StreamString strm;
199 if (m_type == eTypeClassMethod)
200 strm.PutChar('+');
201 else if (m_type == eTypeInstanceMethod)
202 strm.PutChar('-');
203 strm.Printf("[%s %s]", GetClassName().GetCString(),
204 GetSelector().GetCString());
205 return ConstString(strm.GetString());
206 }
207
208 if (!empty_if_no_category) {
209 // Just return the full name since it doesn't have a category
210 return GetFullName();
211 }
212 }
213 return ConstString();
214}
215
216std::vector<Language::MethodNameVariant>
218 std::vector<Language::MethodNameVariant> variant_names;
219 ObjCLanguage::MethodName objc_method(method_name.GetCString(), false);
220 if (!objc_method.IsValid(false)) {
221 return variant_names;
222 }
223
224 variant_names.emplace_back(objc_method.GetSelector(),
225 lldb::eFunctionNameTypeSelector);
226
227 const bool is_class_method =
228 objc_method.GetType() == MethodName::eTypeClassMethod;
229 const bool is_instance_method =
231 ConstString name_sans_category =
232 objc_method.GetFullNameWithoutCategory(/*empty_if_no_category*/ true);
233
234 if (is_class_method || is_instance_method) {
235 if (name_sans_category)
236 variant_names.emplace_back(name_sans_category,
237 lldb::eFunctionNameTypeFull);
238 } else {
239 StreamString strm;
240
241 strm.Printf("+%s", objc_method.GetFullName().GetCString());
242 variant_names.emplace_back(ConstString(strm.GetString()),
243 lldb::eFunctionNameTypeFull);
244 strm.Clear();
245
246 strm.Printf("-%s", objc_method.GetFullName().GetCString());
247 variant_names.emplace_back(ConstString(strm.GetString()),
248 lldb::eFunctionNameTypeFull);
249 strm.Clear();
250
251 if (name_sans_category) {
252 strm.Printf("+%s", name_sans_category.GetCString());
253 variant_names.emplace_back(ConstString(strm.GetString()),
254 lldb::eFunctionNameTypeFull);
255 strm.Clear();
256
257 strm.Printf("-%s", name_sans_category.GetCString());
258 variant_names.emplace_back(ConstString(strm.GetString()),
259 lldb::eFunctionNameTypeFull);
260 }
261 }
262
263 return variant_names;
264}
265
266bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
267 ConstString demangled_name = mangled.GetDemangledName();
268 if (!demangled_name)
269 return false;
270 return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
271}
272
273static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
274 if (!objc_category_sp)
275 return;
276
277 TypeSummaryImpl::Flags objc_flags;
278 objc_flags.SetCascades(false)
279 .SetSkipPointers(true)
280 .SetSkipReferences(true)
282 .SetDontShowValue(true)
284 .SetHideItemNames(false);
285
286 lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(
288 objc_category_sp->AddTypeSummary("BOOL", eFormatterMatchExact,
289 ObjC_BOOL_summary);
290 objc_category_sp->AddTypeSummary("BOOL &", eFormatterMatchExact,
291 ObjC_BOOL_summary);
292 objc_category_sp->AddTypeSummary("BOOL *", eFormatterMatchExact,
293 ObjC_BOOL_summary);
294
295 // we need to skip pointers here since we are special casing a SEL* when
296 // retrieving its value
297 objc_flags.SetSkipPointers(true);
298 AddCXXSummary(objc_category_sp,
300 "SEL summary provider", ConstString("SEL"), objc_flags);
303 "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
306 "SEL summary provider", ConstString("objc_selector"), objc_flags);
309 "SEL summary provider", ConstString("objc_selector *"), objc_flags);
310 AddCXXSummary(objc_category_sp,
312 "SEL summary provider", ConstString("SEL *"), objc_flags);
313
314 AddCXXSummary(objc_category_sp,
316 "Class summary provider", ConstString("Class"), objc_flags);
317
318 SyntheticChildren::Flags class_synth_flags;
319 class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
320 false);
321
322 AddCXXSynthetic(objc_category_sp,
324 "Class synthetic children", ConstString("Class"),
325 class_synth_flags);
326
327 objc_flags.SetSkipPointers(false);
328 objc_flags.SetCascades(true);
329 objc_flags.SetSkipReferences(false);
330
331 AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
332 ConstString("__block_literal_generic"), objc_flags);
333
334 AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} "
335 "months, ${var.days} days, ${var.hours} "
336 "hours, ${var.minutes} minutes "
337 "${var.seconds} seconds",
338 ConstString("CFGregorianUnits"), objc_flags);
339 AddStringSummary(objc_category_sp,
340 "location=${var.location} length=${var.length}",
341 ConstString("CFRange"), objc_flags);
342
343 AddStringSummary(objc_category_sp,
344 "location=${var.location}, length=${var.length}",
345 ConstString("NSRange"), objc_flags);
346 AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
347 ConstString("NSRectArray"), objc_flags);
348
349 AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags);
350 AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags);
351 AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags);
352
353 AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags);
354 AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags);
355 AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags);
356
357 AddStringSummary(objc_category_sp,
358 "red=${var.red} green=${var.green} blue=${var.blue}",
359 ConstString("RGBColor"), objc_flags);
361 objc_category_sp,
362 "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
363 ConstString("Rect"), objc_flags);
364 AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}",
365 ConstString("Point"), objc_flags);
366 AddStringSummary(objc_category_sp,
367 "${var.month}/${var.day}/${var.year} ${var.hour} "
368 ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
369 ConstString("DateTimeRect *"), objc_flags);
370 AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/"
371 "${var.ld.year} ${var.ld.hour} "
372 ":${var.ld.minute} :${var.ld.second} "
373 "dayOfWeek:${var.ld.dayOfWeek}",
374 ConstString("LongDateRect"), objc_flags);
375 AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})",
376 ConstString("HIPoint"), objc_flags);
377 AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
378 ConstString("HIRect"), objc_flags);
379
380 TypeSummaryImpl::Flags appkit_flags;
381 appkit_flags.SetCascades(true)
382 .SetSkipPointers(false)
383 .SetSkipReferences(false)
385 .SetDontShowValue(false)
387 .SetHideItemNames(false);
388
389 appkit_flags.SetDontShowChildren(false);
390
393 "NSArray summary provider", ConstString("NSArray"), appkit_flags);
396 "NSArray summary provider", ConstString("NSConstantArray"), appkit_flags);
399 "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
402 "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
405 "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
406 AddCXXSummary(objc_category_sp,
408 "NSArray summary provider",
409 ConstString("__NSSingleObjectArrayI"), appkit_flags);
412 "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
415 "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
418 "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags);
421 "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
422 AddCXXSummary(objc_category_sp,
424 "NSArray summary provider", ConstString("CFMutableArrayRef"),
425 appkit_flags);
426
427 AddCXXSummary(objc_category_sp,
429 "NSDictionary summary provider", ConstString("NSDictionary"),
430 appkit_flags);
431 AddCXXSummary(objc_category_sp,
433 "NSDictionary summary provider",
434 ConstString("NSConstantDictionary"), appkit_flags);
435 AddCXXSummary(objc_category_sp,
437 "NSDictionary summary provider",
438 ConstString("NSMutableDictionary"), appkit_flags);
439 AddCXXSummary(objc_category_sp,
441 "NSDictionary summary provider",
442 ConstString("__NSCFDictionary"), appkit_flags);
443 AddCXXSummary(objc_category_sp,
445 "NSDictionary summary provider", ConstString("__NSDictionaryI"),
446 appkit_flags);
447 AddCXXSummary(objc_category_sp,
449 "NSDictionary summary provider",
450 ConstString("__NSSingleEntryDictionaryI"), appkit_flags);
451 AddCXXSummary(objc_category_sp,
453 "NSDictionary summary provider", ConstString("__NSDictionaryM"),
454 appkit_flags);
455 AddCXXSummary(objc_category_sp,
457 "NSDictionary summary provider", ConstString("CFDictionaryRef"),
458 appkit_flags);
459 AddCXXSummary(objc_category_sp,
461 "NSDictionary summary provider", ConstString("__CFDictionary"),
462 appkit_flags);
463 AddCXXSummary(objc_category_sp,
465 "NSDictionary summary provider",
466 ConstString("CFMutableDictionaryRef"), appkit_flags);
467
468 AddCXXSummary(objc_category_sp,
469 lldb_private::formatters::NSSetSummaryProvider<false>,
470 "NSSet summary", ConstString("NSSet"), appkit_flags);
472 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
473 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
474 AddCXXSummary(objc_category_sp,
475 lldb_private::formatters::NSSetSummaryProvider<true>,
476 "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
478 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>,
479 "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
480 AddCXXSummary(objc_category_sp,
481 lldb_private::formatters::NSSetSummaryProvider<false>,
482 "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
483 AddCXXSummary(objc_category_sp,
484 lldb_private::formatters::NSSetSummaryProvider<false>,
485 "__CFSet summary", ConstString("__CFSet"), appkit_flags);
486 AddCXXSummary(objc_category_sp,
487 lldb_private::formatters::NSSetSummaryProvider<false>,
488 "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
489 AddCXXSummary(objc_category_sp,
490 lldb_private::formatters::NSSetSummaryProvider<false>,
491 "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
493 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
494 "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
496 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
497 "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
499 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
500 "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
502 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
503 "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
505 objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
506 "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
507
510 "NSError summary provider", ConstString("NSError"), appkit_flags);
513 "NSException summary provider", ConstString("NSException"), appkit_flags);
514
515 // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
516 // ConstString("$_lldb_typegen_nspair"), appkit_flags);
517
518 appkit_flags.SetDontShowChildren(true);
519
520 AddCXXSynthetic(objc_category_sp,
522 "NSArray synthetic children", ConstString("__NSArrayM"),
524 AddCXXSynthetic(objc_category_sp,
526 "NSArray synthetic children", ConstString("__NSArrayI"),
528 AddCXXSynthetic(objc_category_sp,
530 "NSArray synthetic children", ConstString("__NSArray0"),
532 AddCXXSynthetic(objc_category_sp,
534 "NSArray synthetic children",
535 ConstString("__NSSingleObjectArrayI"),
537 AddCXXSynthetic(objc_category_sp,
539 "NSArray synthetic children", ConstString("NSArray"),
541 AddCXXSynthetic(objc_category_sp,
543 "NSArray synthetic children", ConstString("NSConstantArray"),
545 AddCXXSynthetic(objc_category_sp,
547 "NSArray synthetic children", ConstString("NSMutableArray"),
549 AddCXXSynthetic(objc_category_sp,
551 "NSArray synthetic children", ConstString("__NSCFArray"),
553 AddCXXSynthetic(objc_category_sp,
555 "NSArray synthetic children", ConstString("_NSCallStackArray"),
557 AddCXXSynthetic(objc_category_sp,
559 "NSArray synthetic children",
560 ConstString("CFMutableArrayRef"),
562 AddCXXSynthetic(objc_category_sp,
564 "NSArray synthetic children", ConstString("CFArrayRef"),
566
568 objc_category_sp,
570 "NSDictionary synthetic children", ConstString("__NSDictionaryM"),
573 objc_category_sp,
575 "NSDictionary synthetic children", ConstString("NSConstantDictionary"),
578 objc_category_sp,
580 "NSDictionary synthetic children", ConstString("__NSDictionaryI"),
583 objc_category_sp,
585 "NSDictionary synthetic children",
586 ConstString("__NSSingleEntryDictionaryI"),
589 objc_category_sp,
591 "NSDictionary synthetic children", ConstString("__NSCFDictionary"),
594 objc_category_sp,
596 "NSDictionary synthetic children", ConstString("NSDictionary"),
599 objc_category_sp,
601 "NSDictionary synthetic children", ConstString("NSMutableDictionary"),
604 objc_category_sp,
606 "NSDictionary synthetic children", ConstString("CFDictionaryRef"),
609 objc_category_sp,
611 "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"),
614 objc_category_sp,
616 "NSDictionary synthetic children", ConstString("__CFDictionary"),
618
619 AddCXXSynthetic(objc_category_sp,
621 "NSError synthetic children", ConstString("NSError"),
623 AddCXXSynthetic(objc_category_sp,
625 "NSException synthetic children", ConstString("NSException"),
627
628 AddCXXSynthetic(objc_category_sp,
630 "NSSet synthetic children", ConstString("NSSet"),
632 AddCXXSynthetic(objc_category_sp,
634 "__NSSetI synthetic children", ConstString("__NSSetI"),
636 AddCXXSynthetic(objc_category_sp,
638 "__NSSetM synthetic children", ConstString("__NSSetM"),
640 AddCXXSynthetic(objc_category_sp,
642 "__NSCFSet synthetic children", ConstString("__NSCFSet"),
644 AddCXXSynthetic(objc_category_sp,
646 "CFSetRef synthetic children", ConstString("CFSetRef"),
648
651 "NSMutableSet synthetic children", ConstString("NSMutableSet"),
655 "NSOrderedSet synthetic children", ConstString("NSOrderedSet"),
659 "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"),
663 "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"),
665 AddCXXSynthetic(objc_category_sp,
667 "__CFSet synthetic children", ConstString("__CFSet"),
669
670 AddCXXSynthetic(objc_category_sp,
672 "NSIndexPath synthetic children", ConstString("NSIndexPath"),
674
677 "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
678 AddCXXSummary(objc_category_sp,
680 "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
681 AddCXXSummary(objc_category_sp,
683 "CFBag summary provider", ConstString("const struct __CFBag"),
684 appkit_flags);
687 "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
688
689 AddCXXSummary(objc_category_sp,
691 "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"),
692 appkit_flags);
693 AddCXXSummary(objc_category_sp,
695 "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"),
696 appkit_flags);
697
700 "NSString summary provider", ConstString("NSString"), appkit_flags);
703 "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
706 "NSString summary provider", ConstString("__CFString"), appkit_flags);
707 AddCXXSummary(objc_category_sp,
709 "NSString summary provider", ConstString("CFMutableStringRef"),
710 appkit_flags);
711 AddCXXSummary(objc_category_sp,
713 "NSString summary provider", ConstString("NSMutableString"),
714 appkit_flags);
715 AddCXXSummary(objc_category_sp,
717 "NSString summary provider",
718 ConstString("__NSCFConstantString"), appkit_flags);
721 "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
722 AddCXXSummary(objc_category_sp,
724 "NSString summary provider", ConstString("NSCFConstantString"),
725 appkit_flags);
728 "NSString summary provider", ConstString("NSCFString"), appkit_flags);
731 "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
732 AddCXXSummary(objc_category_sp,
734 "NSString summary provider",
735 ConstString("NSTaggedPointerString"), appkit_flags);
736
737 AddCXXSummary(objc_category_sp,
739 "NSAttributedString summary provider",
740 ConstString("NSAttributedString"), appkit_flags);
742 objc_category_sp,
744 "NSMutableAttributedString summary provider",
745 ConstString("NSMutableAttributedString"), appkit_flags);
747 objc_category_sp,
749 "NSMutableAttributedString summary provider",
750 ConstString("NSConcreteMutableAttributedString"), appkit_flags);
751
754 "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
755
756 AddCXXSummary(objc_category_sp,
758 "NSData summary provider", ConstString("NSData"), appkit_flags);
761 "NSData summary provider", ConstString("_NSInlineData"), appkit_flags);
764 "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
765 AddCXXSummary(objc_category_sp,
767 "NSData summary provider", ConstString("NSConcreteMutableData"),
768 appkit_flags);
771 "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
774 "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
777 "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
780 "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
781
784 "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
785
786 AddCXXSummary(objc_category_sp,
788 "NSNotification summary provider",
789 ConstString("NSNotification"), appkit_flags);
790 AddCXXSummary(objc_category_sp,
792 "NSNotification summary provider",
793 ConstString("NSConcreteNotification"), appkit_flags);
794
797 "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
798 AddCXXSummary(objc_category_sp,
800 "NSNumber summary provider",
801 ConstString("NSConstantIntegerNumber"), appkit_flags);
802 AddCXXSummary(objc_category_sp,
804 "NSNumber summary provider",
805 ConstString("NSConstantDoubleNumber"), appkit_flags);
806 AddCXXSummary(objc_category_sp,
808 "NSNumber summary provider",
809 ConstString("NSConstantFloatNumber"), appkit_flags);
812 "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
815 "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
818 "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
821 "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
824 "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
825 AddCXXSummary(objc_category_sp,
827 "NSDecimalNumber summary provider",
828 ConstString("NSDecimalNumber"), appkit_flags);
829
830 AddCXXSummary(objc_category_sp,
832 "NSURL summary provider", ConstString("NSURL"), appkit_flags);
835 "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
836
837 AddCXXSummary(objc_category_sp,
839 "NSDate summary provider", ConstString("NSDate"), appkit_flags);
842 "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
845 "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
848 "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
849
852 "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
853 AddCXXSummary(objc_category_sp,
855 "NSTimeZone summary provider", ConstString("CFTimeZoneRef"),
856 appkit_flags);
859 "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
860
861 // CFAbsoluteTime is actually a double rather than a pointer to an object we
862 // do not care about the numeric value, since it is probably meaningless to
863 // users
864 appkit_flags.SetDontShowValue(true);
865 AddCXXSummary(objc_category_sp,
867 "CFAbsoluteTime summary provider",
868 ConstString("CFAbsoluteTime"), appkit_flags);
869 appkit_flags.SetDontShowValue(false);
870
873 "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
874 AddCXXSummary(objc_category_sp,
876 "NSIndexSet summary provider", ConstString("NSMutableIndexSet"),
877 appkit_flags);
878
879 AddStringSummary(objc_category_sp,
880 "@\"${var.month%d}/${var.day%d}/${var.year%d} "
881 "${var.hour%d}:${var.minute%d}:${var.second}\"",
882 ConstString("CFGregorianDate"), appkit_flags);
883
884 AddCXXSummary(objc_category_sp,
886 "CFBitVector summary provider", ConstString("CFBitVectorRef"),
887 appkit_flags);
888 AddCXXSummary(objc_category_sp,
890 "CFBitVector summary provider",
891 ConstString("CFMutableBitVectorRef"), appkit_flags);
892 AddCXXSummary(objc_category_sp,
894 "CFBitVector summary provider", ConstString("__CFBitVector"),
895 appkit_flags);
896 AddCXXSummary(objc_category_sp,
898 "CFBitVector summary provider",
899 ConstString("__CFMutableBitVector"), appkit_flags);
900}
901
902static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
903 if (!objc_category_sp)
904 return;
905
906 TypeSummaryImpl::Flags cm_flags;
907 cm_flags.SetCascades(true)
908 .SetDontShowChildren(false)
909 .SetDontShowValue(false)
910 .SetHideItemNames(false)
912 .SetSkipPointers(false)
913 .SetSkipReferences(false);
914
915 AddCXXSummary(objc_category_sp,
917 "CMTime summary provider", ConstString("CMTime"), cm_flags);
918}
919
920lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() {
921 static llvm::once_flag g_initialize;
922 static TypeCategoryImplSP g_category;
923
924 llvm::call_once(g_initialize, [this]() -> void {
926 g_category);
927 if (g_category) {
928 LoadCoreMediaFormatters(g_category);
929 LoadObjCFormatters(g_category);
930 }
931 });
932 return g_category;
933}
934
935std::vector<FormattersMatchCandidate>
937 lldb::DynamicValueType use_dynamic) {
938 std::vector<FormattersMatchCandidate> result;
939
940 if (use_dynamic == lldb::eNoDynamicValues)
941 return result;
942
943 CompilerType compiler_type(valobj.GetCompilerType());
944
945 const bool check_cpp = false;
946 const bool check_objc = true;
947 bool canBeObjCDynamic =
948 compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
949
950 if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
951 do {
952 lldb::ProcessSP process_sp = valobj.GetProcessSP();
953 if (!process_sp)
954 break;
955 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
956 if (runtime == nullptr)
957 break;
959 runtime->GetClassDescriptor(valobj));
960 if (!objc_class_sp)
961 break;
962 if (ConstString name = objc_class_sp->GetClassName())
963 result.push_back(
964 {name, valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(),
965 TypeImpl(objc_class_sp->GetType()),
967 } while (false);
968 }
969
970 return result;
971}
972
973std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
974 class ObjCScavengerResult : public Language::TypeScavenger::Result {
975 public:
976 ObjCScavengerResult(CompilerType type)
977 : Language::TypeScavenger::Result(), m_compiler_type(type) {}
978
979 bool IsValid() override { return m_compiler_type.IsValid(); }
980
981 bool DumpToStream(Stream &stream, bool print_help_if_available) override {
982 if (IsValid()) {
983 m_compiler_type.DumpTypeDescription(&stream);
984 stream.EOL();
985 return true;
986 }
987 return false;
988 }
989
990 private:
991 CompilerType m_compiler_type;
992 };
993
994 class ObjCRuntimeScavenger : public Language::TypeScavenger {
995 protected:
996 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
997 ResultSet &results) override {
998 bool result = false;
999
1000 if (auto *process = exe_scope->CalculateProcess().get()) {
1001 if (auto *objc_runtime = ObjCLanguageRuntime::Get(*process)) {
1002 if (auto *decl_vendor = objc_runtime->GetDeclVendor()) {
1003 ConstString name(key);
1004 for (const CompilerType &type :
1005 decl_vendor->FindTypes(name, /*max_matches*/ UINT32_MAX)) {
1006 result = true;
1007 std::unique_ptr<Language::TypeScavenger::Result> result(
1008 new ObjCScavengerResult(type));
1009 results.insert(std::move(result));
1010 }
1011 }
1012 }
1013 }
1014
1015 return result;
1016 }
1017
1018 friend class lldb_private::ObjCLanguage;
1019 };
1020
1021 class ObjCModulesScavenger : public Language::TypeScavenger {
1022 protected:
1023 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
1024 ResultSet &results) override {
1025 bool result = false;
1026
1027 if (auto *target = exe_scope->CalculateTarget().get()) {
1028 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
1029 target->GetPersistentExpressionStateForLanguage(
1031 if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
1032 persistent_vars->GetClangModulesDeclVendor()) {
1033 ConstString key_cs(key);
1034 auto types = clang_modules_decl_vendor->FindTypes(
1035 key_cs, /*max_matches*/ UINT32_MAX);
1036 if (!types.empty()) {
1037 result = true;
1038 std::unique_ptr<Language::TypeScavenger::Result> result(
1039 new ObjCScavengerResult(types.front()));
1040 results.insert(std::move(result));
1041 }
1042 }
1043 }
1044
1045 return result;
1046 }
1047
1048 friend class lldb_private::ObjCLanguage;
1049 };
1050
1051 class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
1052 public:
1053 CompilerType AdjustForInclusion(CompilerType &candidate) override {
1054 LanguageType lang_type(candidate.GetMinimumLanguage());
1055 if (!Language::LanguageIsObjC(lang_type))
1056 return CompilerType();
1057 if (candidate.IsTypedefType())
1058 return candidate.GetTypedefedType();
1059 return candidate;
1060 }
1061 };
1062
1063 return std::unique_ptr<TypeScavenger>(
1064 new Language::EitherTypeScavenger<ObjCModulesScavenger,
1065 ObjCRuntimeScavenger,
1066 ObjCDebugInfoScavenger>());
1067}
1068
1070 ConstString type_hint,
1071 std::string &prefix,
1072 std::string &suffix) {
1073 static ConstString g_CFBag("CFBag");
1074 static ConstString g_CFBinaryHeap("CFBinaryHeap");
1075
1076 static ConstString g_NSNumberChar("NSNumber:char");
1077 static ConstString g_NSNumberShort("NSNumber:short");
1078 static ConstString g_NSNumberInt("NSNumber:int");
1079 static ConstString g_NSNumberLong("NSNumber:long");
1080 static ConstString g_NSNumberInt128("NSNumber:int128_t");
1081 static ConstString g_NSNumberFloat("NSNumber:float");
1082 static ConstString g_NSNumberDouble("NSNumber:double");
1083
1084 static ConstString g_NSData("NSData");
1085 static ConstString g_NSArray("NSArray");
1086 static ConstString g_NSString("NSString");
1087 static ConstString g_NSStringStar("NSString*");
1088
1089 if (type_hint.IsEmpty())
1090 return false;
1091
1092 prefix.clear();
1093 suffix.clear();
1094
1095 if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) {
1096 prefix = "@";
1097 return true;
1098 }
1099
1100 if (type_hint == g_NSNumberChar) {
1101 prefix = "(char)";
1102 return true;
1103 }
1104 if (type_hint == g_NSNumberShort) {
1105 prefix = "(short)";
1106 return true;
1107 }
1108 if (type_hint == g_NSNumberInt) {
1109 prefix = "(int)";
1110 return true;
1111 }
1112 if (type_hint == g_NSNumberLong) {
1113 prefix = "(long)";
1114 return true;
1115 }
1116 if (type_hint == g_NSNumberInt128) {
1117 prefix = "(int128_t)";
1118 return true;
1119 }
1120 if (type_hint == g_NSNumberFloat) {
1121 prefix = "(float)";
1122 return true;
1123 }
1124 if (type_hint == g_NSNumberDouble) {
1125 prefix = "(double)";
1126 return true;
1127 }
1128
1129 if (type_hint == g_NSData || type_hint == g_NSArray) {
1130 prefix = "@\"";
1131 suffix = "\"";
1132 return true;
1133 }
1134
1135 if (type_hint == g_NSString || type_hint == g_NSStringStar) {
1136 prefix = "@";
1137 return true;
1138 }
1139
1140 return false;
1141}
1142
1144 const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1145 bool isObjCpointer =
1146 (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1147 if (!isObjCpointer)
1148 return false;
1149 bool canReadValue = true;
1150 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1151 return canReadValue && isZero;
1152}
1153
1154bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
1155 const auto suffixes = {".h", ".m", ".M"};
1156 for (auto suffix : suffixes) {
1157 if (file_path.endswith_insensitive(suffix))
1158 return true;
1159 }
1160 return false;
1161}
static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
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.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
Definition: ConstString.h:39
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:303
void Clear()
Clear this object's state.
Definition: ConstString.h:231
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:215
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
static bool LanguageIsObjC(lldb::LanguageType language)
Definition: Language.cpp:262
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
ConstString GetFullNameWithoutCategory(bool empty_if_no_category)
bool IsValid(bool strict) const
Definition: ObjCLanguage.h:45
bool SetName(const char *name, bool strict)
llvm::StringRef GetPluginName() override
Definition: ObjCLanguage.h:161
bool GetFormatterPrefixSuffix(ValueObject &valobj, ConstString type_hint, std::string &prefix, std::string &suffix) override
static lldb_private::Language * CreateInstance(lldb::LanguageType language)
std::unique_ptr< TypeScavenger > GetTypeScavenger() override
lldb::TypeCategoryImplSP GetFormatters() override
bool SymbolNameFitsToLanguage(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
std::vector< FormattersMatchCandidate > GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) override
std::vector< Language::MethodNameVariant > GetMethodNameVariants(ConstString method_name) const override
bool IsNilReference(ValueObject &valobj) override
static bool IsPossibleObjCMethodName(const char *name)
Definition: ObjCLanguage.h:138
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:107
size_t PutChar(char ch)
Definition: Stream.cpp:104
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
Flags & SetSkipReferences(bool value=true)
Flags & SetSkipPointers(bool value=true)
Flags & SetCascades(bool value=true)
Flags & SetCascades(bool value=true)
Definition: TypeSummary.h:82
Flags & SetSkipPointers(bool value=true)
Definition: TypeSummary.h:95
Flags & SetHideItemNames(bool value=true)
Definition: TypeSummary.h:173
Flags & SetDontShowChildren(bool value=true)
Definition: TypeSummary.h:121
Flags & SetSkipReferences(bool value=true)
Definition: TypeSummary.h:108
Flags & SetShowMembersOneLiner(bool value=true)
Definition: TypeSummary.h:160
Flags & SetDontShowValue(bool value=true)
Definition: TypeSummary.h:147
CompilerType GetCompilerType()
Definition: ValueObject.h:352
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:338
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
lldb::TargetSP GetTargetSP() const
Definition: ValueObject.h:334
#define UINT32_MAX
Definition: lldb-defines.h:19
bool NSMutableAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:313
bool NSURLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:766
bool CMTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CoreMedia.cpp:22
template bool NSDataSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
void AddCXXSynthetic(TypeCategoryImpl::SharedPointer category_sp, CXXSyntheticChildren::CreateFrontEndCallback generator, const char *description, ConstString type_name, ScriptedSyntheticChildren::Flags flags, bool regex=false)
Add a synthetic that is implemented by a C++ callback.
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:45
SyntheticChildrenFrontEnd * NSArraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSArray.cpp:792
bool ObjCBOOLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:1115
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:227
bool NSBundleSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:40
bool NSIndexSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:235
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:29
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
template bool NSDictionarySummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
template bool ObjCSELSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char *string, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
void AddCXXSummary(TypeCategoryImpl::SharedPointer category_sp, CXXFunctionSummaryFormat::Callback funct, const char *description, ConstString 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:284
bool NSArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSArray.cpp:335
template bool NSDictionarySummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
template bool ObjCSELSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
SyntheticChildrenFrontEnd * NSSetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSSet.cpp:340
bool NSDateSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:892
SyntheticChildrenFrontEnd * NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:140
bool NSMachPortSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:189
template bool NSDataSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSError_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSError.cpp:55
bool ObjCClassSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:994
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:424
bool NSTimeZoneSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:91
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:33
SyntheticChildrenFrontEnd * NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
void AddOneLineSummary(TypeCategoryImpl::SharedPointer category_sp, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
SyntheticChildrenFrontEnd * ObjCClassSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: Cocoa.cpp:1046
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:109
SyntheticChildrenFrontEnd * NSErrorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
Definition: NSError.cpp:190
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
LanguageType
Programming language type.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
@ eFormatterMatchExact
@ eNoDynamicValues
static bool IsClangType(const CompilerType &ct)
Definition: ClangUtil.cpp:17