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
63std::optional<const ObjCLanguage::MethodName>
64ObjCLanguage::MethodName::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::MethodName 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;
159 if (m_type != eTypeUnspecified)
160 total_size++; // For + or -
161
162 std::string name_sans_category;
163 name_sans_category.reserve(total_size);
164
165 if (m_type == eTypeClassMethod)
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>
181 std::vector<Language::MethodNameVariant> variant_names;
182 std::optional<const ObjCLanguage::MethodName> objc_method =
184 if (!objc_method)
185 return variant_names;
186
187 variant_names.emplace_back(ConstString(objc_method->GetSelector()),
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(ConstString(name_sans_category.c_str()),
196 lldb::eFunctionNameTypeFull);
197 } else {
198 StreamString strm;
199
200 strm.Printf("+%s", objc_method->GetFullName().c_str());
201 variant_names.emplace_back(ConstString(strm.GetString()),
202 lldb::eFunctionNameTypeFull);
203 strm.Clear();
204
205 strm.Printf("-%s", objc_method->GetFullName().c_str());
206 variant_names.emplace_back(ConstString(strm.GetString()),
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(ConstString(strm.GetString()),
213 lldb::eFunctionNameTypeFull);
214 strm.Clear();
215
216 strm.Printf("-%s", name_sans_category.c_str());
217 variant_names.emplace_back(ConstString(strm.GetString()),
218 lldb::eFunctionNameTypeFull);
219 }
220 }
221
222 return variant_names;
223}
224
226 ConstString demangled_name = mangled.GetDemangledName();
227 if (!demangled_name)
228 return false;
229 return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
230}
231
232static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
233 if (!objc_category_sp)
234 return;
235
236 TypeSummaryImpl::Flags objc_flags;
237 objc_flags.SetCascades(false)
238 .SetSkipPointers(true)
239 .SetSkipReferences(true)
241 .SetDontShowValue(true)
243 .SetHideItemNames(false);
244
247 objc_category_sp->AddTypeSummary("BOOL", eFormatterMatchExact,
248 ObjC_BOOL_summary);
249 objc_category_sp->AddTypeSummary("BOOL &", eFormatterMatchExact,
250 ObjC_BOOL_summary);
251 objc_category_sp->AddTypeSummary("BOOL *", eFormatterMatchExact,
252 ObjC_BOOL_summary);
253
254 // we need to skip pointers here since we are special casing a SEL* when
255 // retrieving its value
256 objc_flags.SetSkipPointers(true);
257 AddCXXSummary(objc_category_sp,
259 "SEL summary provider", "SEL", objc_flags);
260 AddCXXSummary(objc_category_sp,
262 "SEL summary provider", "struct objc_selector", objc_flags);
263 AddCXXSummary(objc_category_sp,
265 "SEL summary provider", "objc_selector", objc_flags);
266 AddCXXSummary(objc_category_sp,
268 "SEL summary provider", "objc_selector *", objc_flags);
269 AddCXXSummary(objc_category_sp,
271 "SEL summary provider", "SEL *", objc_flags);
272
273 AddCXXSummary(objc_category_sp,
275 "Class summary provider", "Class", objc_flags);
276
277 SyntheticChildren::Flags class_synth_flags;
278 class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
279 false);
280
281 AddCXXSynthetic(objc_category_sp,
283 "Class synthetic children", "Class", class_synth_flags);
284
285 objc_flags.SetSkipPointers(false);
286 objc_flags.SetCascades(true);
287 objc_flags.SetSkipReferences(false);
288
289 AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
290 "__block_literal_generic", objc_flags);
291
292 AddStringSummary(objc_category_sp,
293 "${var.years} years, ${var.months} "
294 "months, ${var.days} days, ${var.hours} "
295 "hours, ${var.minutes} minutes "
296 "${var.seconds} seconds",
297 "CFGregorianUnits", objc_flags);
298 AddStringSummary(objc_category_sp,
299 "location=${var.location} length=${var.length}", "CFRange",
300 objc_flags);
301
302 AddStringSummary(objc_category_sp,
303 "location=${var.location}, length=${var.length}", "NSRange",
304 objc_flags);
305 AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
306 "NSRectArray", objc_flags);
307
308 AddOneLineSummary(objc_category_sp, "NSPoint", objc_flags);
309 AddOneLineSummary(objc_category_sp, "NSSize", objc_flags);
310 AddOneLineSummary(objc_category_sp, "NSRect", objc_flags);
311
312 AddOneLineSummary(objc_category_sp, "CGSize", objc_flags);
313 AddOneLineSummary(objc_category_sp, "CGPoint", objc_flags);
314 AddOneLineSummary(objc_category_sp, "CGRect", objc_flags);
315
316 AddStringSummary(objc_category_sp,
317 "red=${var.red} green=${var.green} blue=${var.blue}",
318 "RGBColor", objc_flags);
320 objc_category_sp,
321 "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", "Rect",
322 objc_flags);
323 AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}", "Point",
324 objc_flags);
325 AddStringSummary(objc_category_sp,
326 "${var.month}/${var.day}/${var.year} ${var.hour} "
327 ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
328 "DateTimeRect *", objc_flags);
329 AddStringSummary(objc_category_sp,
330 "${var.ld.month}/${var.ld.day}/"
331 "${var.ld.year} ${var.ld.hour} "
332 ":${var.ld.minute} :${var.ld.second} "
333 "dayOfWeek:${var.ld.dayOfWeek}",
334 "LongDateRect", objc_flags);
335 AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})", "HIPoint",
336 objc_flags);
337 AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
338 "HIRect", objc_flags);
339
340 TypeSummaryImpl::Flags appkit_flags;
341 appkit_flags.SetCascades(true)
342 .SetSkipPointers(false)
343 .SetSkipReferences(false)
345 .SetDontShowValue(false)
347 .SetHideItemNames(false);
348
349 appkit_flags.SetDontShowChildren(false);
350
351 AddCXXSummary(objc_category_sp,
353 "NSArray summary provider", "NSArray", appkit_flags);
354 AddCXXSummary(objc_category_sp,
356 "NSArray summary provider", "NSConstantArray", appkit_flags);
357 AddCXXSummary(objc_category_sp,
359 "NSArray summary provider", "NSMutableArray", appkit_flags);
360 AddCXXSummary(objc_category_sp,
362 "NSArray summary provider", "__NSArrayI", appkit_flags);
363 AddCXXSummary(objc_category_sp,
365 "NSArray summary provider", "__NSArray0", appkit_flags);
368 "NSArray summary provider", "__NSSingleObjectArrayI", appkit_flags);
369 AddCXXSummary(objc_category_sp,
371 "NSArray summary provider", "__NSArrayM", appkit_flags);
372 AddCXXSummary(objc_category_sp,
374 "NSArray summary provider", "__NSCFArray", appkit_flags);
375 AddCXXSummary(objc_category_sp,
377 "NSArray summary provider", "_NSCallStackArray", appkit_flags);
378 AddCXXSummary(objc_category_sp,
380 "NSArray summary provider", "CFArrayRef", appkit_flags);
381 AddCXXSummary(objc_category_sp,
383 "NSArray summary provider", "CFMutableArrayRef", appkit_flags);
384
385 AddCXXSummary(objc_category_sp,
387 "NSDictionary summary provider", "NSDictionary", appkit_flags);
388 AddCXXSummary(objc_category_sp,
390 "NSDictionary summary provider", "NSConstantDictionary",
391 appkit_flags);
392 AddCXXSummary(objc_category_sp,
394 "NSDictionary summary provider", "NSMutableDictionary",
395 appkit_flags);
396 AddCXXSummary(objc_category_sp,
398 "NSDictionary summary provider", "__NSCFDictionary",
399 appkit_flags);
400 AddCXXSummary(objc_category_sp,
402 "NSDictionary summary provider", "__NSDictionaryI",
403 appkit_flags);
404 AddCXXSummary(objc_category_sp,
406 "NSDictionary summary provider", "__NSSingleEntryDictionaryI",
407 appkit_flags);
408 AddCXXSummary(objc_category_sp,
410 "NSDictionary summary provider", "__NSDictionaryM",
411 appkit_flags);
412 AddCXXSummary(objc_category_sp,
414 "NSDictionary summary provider", "CFDictionaryRef",
415 appkit_flags);
416 AddCXXSummary(objc_category_sp,
418 "NSDictionary summary provider", "__CFDictionary",
419 appkit_flags);
420 AddCXXSummary(objc_category_sp,
422 "NSDictionary summary provider", "CFMutableDictionaryRef",
423 appkit_flags);
424
425 AddCXXSummary(objc_category_sp,
426 lldb_private::formatters::NSSetSummaryProvider<false>,
427 "NSSet summary", "NSSet", appkit_flags);
428 AddCXXSummary(objc_category_sp,
429 lldb_private::formatters::NSSetSummaryProvider<false>,
430 "NSMutableSet summary", "NSMutableSet", appkit_flags);
431 AddCXXSummary(objc_category_sp,
432 lldb_private::formatters::NSSetSummaryProvider<true>,
433 "CFSetRef summary", "CFSetRef", appkit_flags);
434 AddCXXSummary(objc_category_sp,
435 lldb_private::formatters::NSSetSummaryProvider<true>,
436 "CFMutableSetRef summary", "CFMutableSetRef", appkit_flags);
437 AddCXXSummary(objc_category_sp,
438 lldb_private::formatters::NSSetSummaryProvider<false>,
439 "__NSCFSet summary", "__NSCFSet", appkit_flags);
440 AddCXXSummary(objc_category_sp,
441 lldb_private::formatters::NSSetSummaryProvider<false>,
442 "__CFSet summary", "__CFSet", appkit_flags);
443 AddCXXSummary(objc_category_sp,
444 lldb_private::formatters::NSSetSummaryProvider<false>,
445 "__NSSetI summary", "__NSSetI", appkit_flags);
446 AddCXXSummary(objc_category_sp,
447 lldb_private::formatters::NSSetSummaryProvider<false>,
448 "__NSSetM summary", "__NSSetM", appkit_flags);
449 AddCXXSummary(objc_category_sp,
450 lldb_private::formatters::NSSetSummaryProvider<false>,
451 "NSCountedSet summary", "NSCountedSet", appkit_flags);
452 AddCXXSummary(objc_category_sp,
453 lldb_private::formatters::NSSetSummaryProvider<false>,
454 "NSMutableSet summary", "NSMutableSet", appkit_flags);
455 AddCXXSummary(objc_category_sp,
456 lldb_private::formatters::NSSetSummaryProvider<false>,
457 "NSOrderedSet summary", "NSOrderedSet", appkit_flags);
458 AddCXXSummary(objc_category_sp,
459 lldb_private::formatters::NSSetSummaryProvider<false>,
460 "__NSOrderedSetI summary", "__NSOrderedSetI", appkit_flags);
461 AddCXXSummary(objc_category_sp,
462 lldb_private::formatters::NSSetSummaryProvider<false>,
463 "__NSOrderedSetM summary", "__NSOrderedSetM", appkit_flags);
464
465 AddCXXSummary(objc_category_sp,
467 "NSError summary provider", "NSError", appkit_flags);
468 AddCXXSummary(objc_category_sp,
470 "NSException summary provider", "NSException", appkit_flags);
471
472 // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
473 // ConstString("$_lldb_typegen_nspair"), appkit_flags);
474
475 appkit_flags.SetDontShowChildren(true);
476
477 AddCXXSynthetic(objc_category_sp,
479 "NSArray synthetic children", "__NSArrayM",
481 AddCXXSynthetic(objc_category_sp,
483 "NSArray synthetic children", "__NSArrayI",
485 AddCXXSynthetic(objc_category_sp,
487 "NSArray synthetic children", "__NSArray0",
489 AddCXXSynthetic(objc_category_sp,
491 "NSArray synthetic children", "__NSSingleObjectArrayI",
493 AddCXXSynthetic(objc_category_sp,
495 "NSArray synthetic children", "NSArray",
497 AddCXXSynthetic(objc_category_sp,
499 "NSArray synthetic children", "NSConstantArray",
501 AddCXXSynthetic(objc_category_sp,
503 "NSArray synthetic children", "NSMutableArray",
505 AddCXXSynthetic(objc_category_sp,
507 "NSArray synthetic children", "__NSCFArray",
509 AddCXXSynthetic(objc_category_sp,
511 "NSArray synthetic children", "_NSCallStackArray",
513 AddCXXSynthetic(objc_category_sp,
515 "NSArray synthetic children", "CFMutableArrayRef",
517 AddCXXSynthetic(objc_category_sp,
519 "NSArray synthetic children", "CFArrayRef",
521
523 objc_category_sp,
525 "NSDictionary synthetic children", "__NSDictionaryM",
528 objc_category_sp,
530 "NSDictionary synthetic children", "NSConstantDictionary",
533 objc_category_sp,
535 "NSDictionary synthetic children", "__NSDictionaryI",
538 objc_category_sp,
540 "NSDictionary synthetic children", "__NSSingleEntryDictionaryI",
543 objc_category_sp,
545 "NSDictionary synthetic children", "__NSCFDictionary",
548 objc_category_sp,
550 "NSDictionary synthetic children", "NSDictionary",
553 objc_category_sp,
555 "NSDictionary synthetic children", "NSMutableDictionary",
558 objc_category_sp,
560 "NSDictionary synthetic children", "CFDictionaryRef",
563 objc_category_sp,
565 "NSDictionary synthetic children", "CFMutableDictionaryRef",
568 objc_category_sp,
570 "NSDictionary synthetic children", "__CFDictionary",
572
573 AddCXXSynthetic(objc_category_sp,
575 "NSError synthetic children", "NSError",
577 AddCXXSynthetic(objc_category_sp,
579 "NSException synthetic children", "NSException",
581
584 "NSSet synthetic children", "NSSet", ScriptedSyntheticChildren::Flags());
585 AddCXXSynthetic(objc_category_sp,
587 "__NSSetI synthetic children", "__NSSetI",
589 AddCXXSynthetic(objc_category_sp,
591 "__NSSetM synthetic children", "__NSSetM",
593 AddCXXSynthetic(objc_category_sp,
595 "__NSCFSet synthetic children", "__NSCFSet",
597 AddCXXSynthetic(objc_category_sp,
599 "CFSetRef synthetic children", "CFSetRef",
601
602 AddCXXSynthetic(objc_category_sp,
604 "NSMutableSet synthetic children", "NSMutableSet",
606 AddCXXSynthetic(objc_category_sp,
608 "NSOrderedSet synthetic children", "NSOrderedSet",
610 AddCXXSynthetic(objc_category_sp,
612 "__NSOrderedSetI synthetic children", "__NSOrderedSetI",
614 AddCXXSynthetic(objc_category_sp,
616 "__NSOrderedSetM synthetic children", "__NSOrderedSetM",
618 AddCXXSynthetic(objc_category_sp,
620 "__CFSet synthetic children", "__CFSet",
622
623 AddCXXSynthetic(objc_category_sp,
625 "NSIndexPath synthetic children", "NSIndexPath",
627
628 AddCXXSummary(objc_category_sp,
630 "CFBag summary provider", "CFBagRef", appkit_flags);
631 AddCXXSummary(objc_category_sp,
633 "CFBag summary provider", "__CFBag", appkit_flags);
634 AddCXXSummary(objc_category_sp,
636 "CFBag summary provider", "const struct __CFBag", appkit_flags);
637 AddCXXSummary(objc_category_sp,
639 "CFBag summary provider", "CFMutableBagRef", appkit_flags);
640
643 "CFBinaryHeap summary provider", "CFBinaryHeapRef", appkit_flags);
646 "CFBinaryHeap summary provider", "__CFBinaryHeap", appkit_flags);
647
648 AddCXXSummary(objc_category_sp,
650 "NSString summary provider", "NSString", appkit_flags);
651 AddCXXSummary(objc_category_sp,
653 "NSString summary provider", "CFStringRef", appkit_flags);
654 AddCXXSummary(objc_category_sp,
656 "NSString summary provider", "__CFString", appkit_flags);
659 "NSString summary provider", "CFMutableStringRef", appkit_flags);
660 AddCXXSummary(objc_category_sp,
662 "NSString summary provider", "NSMutableString", appkit_flags);
665 "NSString summary provider", "__NSCFConstantString", appkit_flags);
666 AddCXXSummary(objc_category_sp,
668 "NSString summary provider", "__NSCFString", appkit_flags);
671 "NSString summary provider", "NSCFConstantString", appkit_flags);
672 AddCXXSummary(objc_category_sp,
674 "NSString summary provider", "NSCFString", appkit_flags);
675 AddCXXSummary(objc_category_sp,
677 "NSString summary provider", "NSPathStore2", appkit_flags);
680 "NSString summary provider", "NSTaggedPointerString", appkit_flags);
681
682 AddCXXSummary(objc_category_sp,
684 "NSAttributedString summary provider", "NSAttributedString",
685 appkit_flags);
687 objc_category_sp,
689 "NSMutableAttributedString summary provider", "NSMutableAttributedString",
690 appkit_flags);
692 objc_category_sp,
694 "NSMutableAttributedString summary provider",
695 "NSConcreteMutableAttributedString", appkit_flags);
696
697 AddCXXSummary(objc_category_sp,
699 "NSBundle summary provider", "NSBundle", appkit_flags);
700
701 AddCXXSummary(objc_category_sp,
703 "NSData summary provider", "NSData", appkit_flags);
704 AddCXXSummary(objc_category_sp,
706 "NSData summary provider", "_NSInlineData", appkit_flags);
707 AddCXXSummary(objc_category_sp,
709 "NSData summary provider", "NSConcreteData", appkit_flags);
712 "NSData summary provider", "NSConcreteMutableData", appkit_flags);
713 AddCXXSummary(objc_category_sp,
715 "NSData summary provider", "NSMutableData", appkit_flags);
716 AddCXXSummary(objc_category_sp,
718 "NSData summary provider", "__NSCFData", appkit_flags);
719 AddCXXSummary(objc_category_sp,
721 "NSData summary provider", "CFDataRef", appkit_flags);
722 AddCXXSummary(objc_category_sp,
724 "NSData summary provider", "CFMutableDataRef", appkit_flags);
725
726 AddCXXSummary(objc_category_sp,
728 "NSMachPort summary provider", "NSMachPort", appkit_flags);
729
732 "NSNotification summary provider", "NSNotification", appkit_flags);
733 AddCXXSummary(objc_category_sp,
735 "NSNotification summary provider", "NSConcreteNotification",
736 appkit_flags);
737
738 AddCXXSummary(objc_category_sp,
740 "NSNumber summary provider", "NSNumber", appkit_flags);
743 "NSNumber summary provider", "NSConstantIntegerNumber", appkit_flags);
746 "NSNumber summary provider", "NSConstantDoubleNumber", appkit_flags);
749 "NSNumber summary provider", "NSConstantFloatNumber", appkit_flags);
750 AddCXXSummary(objc_category_sp,
752 "CFNumberRef summary provider", "CFNumberRef", appkit_flags);
753 AddCXXSummary(objc_category_sp,
755 "NSNumber summary provider", "__NSCFBoolean", appkit_flags);
756 AddCXXSummary(objc_category_sp,
758 "NSNumber summary provider", "__NSCFNumber", appkit_flags);
759 AddCXXSummary(objc_category_sp,
761 "NSNumber summary provider", "NSCFBoolean", appkit_flags);
762 AddCXXSummary(objc_category_sp,
764 "NSNumber summary provider", "NSCFNumber", appkit_flags);
767 "NSDecimalNumber summary provider", "NSDecimalNumber", appkit_flags);
768
769 AddCXXSummary(objc_category_sp,
771 "NSURL summary provider", "NSURL", appkit_flags);
772 AddCXXSummary(objc_category_sp,
774 "NSURL summary provider", "CFURLRef", appkit_flags);
775
776 AddCXXSummary(objc_category_sp,
778 "NSDate summary provider", "NSDate", appkit_flags);
779 AddCXXSummary(objc_category_sp,
781 "NSDate summary provider", "__NSDate", appkit_flags);
782 AddCXXSummary(objc_category_sp,
784 "NSDate summary provider", "__NSTaggedDate", appkit_flags);
785 AddCXXSummary(objc_category_sp,
787 "NSDate summary provider", "NSCalendarDate", appkit_flags);
788
789 AddCXXSummary(objc_category_sp,
791 "NSTimeZone summary provider", "NSTimeZone", appkit_flags);
792 AddCXXSummary(objc_category_sp,
794 "NSTimeZone summary provider", "CFTimeZoneRef", appkit_flags);
795 AddCXXSummary(objc_category_sp,
797 "NSTimeZone summary provider", "__NSTimeZone", appkit_flags);
798
799 // CFAbsoluteTime is actually a double rather than a pointer to an object we
800 // do not care about the numeric value, since it is probably meaningless to
801 // users
802 appkit_flags.SetDontShowValue(true);
805 "CFAbsoluteTime summary provider", "CFAbsoluteTime", appkit_flags);
806 appkit_flags.SetDontShowValue(false);
807
808 AddCXXSummary(objc_category_sp,
810 "NSIndexSet summary provider", "NSIndexSet", appkit_flags);
813 "NSIndexSet summary provider", "NSMutableIndexSet", appkit_flags);
814
815 AddStringSummary(objc_category_sp,
816 "@\"${var.month%d}/${var.day%d}/${var.year%d} "
817 "${var.hour%d}:${var.minute%d}:${var.second}\"",
818 "CFGregorianDate", appkit_flags);
819
820 AddCXXSummary(objc_category_sp,
822 "CFBitVector summary provider", "CFBitVectorRef", appkit_flags);
825 "CFBitVector summary provider", "CFMutableBitVectorRef", appkit_flags);
826 AddCXXSummary(objc_category_sp,
828 "CFBitVector summary provider", "__CFBitVector", appkit_flags);
831 "CFBitVector summary provider", "__CFMutableBitVector", appkit_flags);
832}
833
834static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
835 if (!objc_category_sp)
836 return;
837
838 TypeSummaryImpl::Flags cm_flags;
839 cm_flags.SetCascades(true)
840 .SetDontShowChildren(false)
841 .SetDontShowValue(false)
842 .SetHideItemNames(false)
844 .SetSkipPointers(false)
845 .SetSkipReferences(false);
846
847 AddCXXSummary(objc_category_sp,
849 "CMTime summary provider", "CMTime", cm_flags);
850}
851
853 static llvm::once_flag g_initialize;
854 static TypeCategoryImplSP g_category;
855
856 llvm::call_once(g_initialize, [this]() -> void {
858 g_category);
859 if (g_category) {
860 LoadCoreMediaFormatters(g_category);
861 LoadObjCFormatters(g_category);
862 }
863 });
864 return g_category;
865}
866
867std::vector<FormattersMatchCandidate>
869 lldb::DynamicValueType use_dynamic) {
870 std::vector<FormattersMatchCandidate> result;
871
872 if (use_dynamic == lldb::eNoDynamicValues)
873 return result;
874
875 CompilerType compiler_type(valobj.GetCompilerType());
876
877 const bool check_cpp = false;
878 const bool check_objc = true;
879 bool canBeObjCDynamic =
880 compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
881
882 if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
883 do {
884 lldb::ProcessSP process_sp = valobj.GetProcessSP();
885 if (!process_sp)
886 break;
887 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
888 if (runtime == nullptr)
889 break;
891 runtime->GetClassDescriptor(valobj));
892 if (!objc_class_sp)
893 break;
894 if (ConstString name = objc_class_sp->GetClassName())
895 result.push_back(
896 {name, valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(),
897 TypeImpl(objc_class_sp->GetType()),
899 } while (false);
900 }
901
902 return result;
903}
904
905std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() {
906 class ObjCScavengerResult : public Language::TypeScavenger::Result {
907 public:
908 ObjCScavengerResult(CompilerType type)
909 : Language::TypeScavenger::Result(), m_compiler_type(type) {}
910
911 bool IsValid() override { return m_compiler_type.IsValid(); }
912
913 bool DumpToStream(Stream &stream, bool print_help_if_available) override {
914 if (IsValid()) {
915 m_compiler_type.DumpTypeDescription(&stream);
916 stream.EOL();
917 return true;
918 }
919 return false;
920 }
921
922 private:
923 CompilerType m_compiler_type;
924 };
925
926 class ObjCRuntimeScavenger : public Language::TypeScavenger {
927 protected:
928 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
929 ResultSet &results) override {
930 bool result = false;
931
932 if (auto *process = exe_scope->CalculateProcess().get()) {
933 if (auto *objc_runtime = ObjCLanguageRuntime::Get(*process)) {
934 if (auto *decl_vendor = objc_runtime->GetDeclVendor()) {
935 ConstString name(key);
936 for (const CompilerType &type :
937 decl_vendor->FindTypes(name, /*max_matches*/ UINT32_MAX)) {
938 result = true;
939 std::unique_ptr<Language::TypeScavenger::Result> result(
940 new ObjCScavengerResult(type));
941 results.insert(std::move(result));
942 }
943 }
944 }
945 }
946
947 return result;
948 }
949
950 friend class lldb_private::ObjCLanguage;
951 };
952
953 class ObjCModulesScavenger : public Language::TypeScavenger {
954 protected:
955 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
956 ResultSet &results) override {
957 bool result = false;
958
959 if (auto *target = exe_scope->CalculateTarget().get()) {
960 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
961 target->GetPersistentExpressionStateForLanguage(
963 if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
964 persistent_vars->GetClangModulesDeclVendor()) {
965 ConstString key_cs(key);
966 auto types = clang_modules_decl_vendor->FindTypes(
967 key_cs, /*max_matches*/ UINT32_MAX);
968 if (!types.empty()) {
969 result = true;
970 std::unique_ptr<Language::TypeScavenger::Result> result(
971 new ObjCScavengerResult(types.front()));
972 results.insert(std::move(result));
973 }
974 }
975 }
976
977 return result;
978 }
979
980 friend class lldb_private::ObjCLanguage;
981 };
982
983 class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
984 public:
985 CompilerType AdjustForInclusion(CompilerType &candidate) override {
986 LanguageType lang_type(candidate.GetMinimumLanguage());
987 if (!Language::LanguageIsObjC(lang_type))
988 return CompilerType();
989 if (candidate.IsTypedefType())
990 return candidate.GetTypedefedType();
991 return candidate;
992 }
993 };
994
995 return std::unique_ptr<TypeScavenger>(
996 new Language::EitherTypeScavenger<ObjCModulesScavenger,
997 ObjCRuntimeScavenger,
998 ObjCDebugInfoScavenger>());
999}
1000
1001std::pair<llvm::StringRef, llvm::StringRef>
1002ObjCLanguage::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {
1003 static constexpr llvm::StringRef empty;
1004 static const llvm::StringMap<
1005 std::pair<const llvm::StringRef, const llvm::StringRef>>
1006 g_affix_map = {
1007 {"CFBag", {"@", empty}},
1008 {"CFBinaryHeap", {"@", empty}},
1009 {"NSString", {"@", empty}},
1010 {"NSString*", {"@", empty}},
1011 {"NSNumber:char", {"(char)", empty}},
1012 {"NSNumber:short", {"(short)", empty}},
1013 {"NSNumber:int", {"(int)", empty}},
1014 {"NSNumber:long", {"(long)", empty}},
1015 {"NSNumber:int128_t", {"(int128_t)", empty}},
1016 {"NSNumber:float", {"(float)", empty}},
1017 {"NSNumber:double", {"(double)", empty}},
1018 {"NSData", {"@\"", "\""}},
1019 {"NSArray", {"@\"", "\""}},
1020 };
1021 return g_affix_map.lookup(type_hint);
1022}
1023
1025 const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1026 bool isObjCpointer =
1027 (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1028 if (!isObjCpointer)
1029 return false;
1030 bool canReadValue = true;
1031 bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1032 return canReadValue && isZero;
1033}
1034
1035bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
1036 const auto suffixes = {".h", ".m", ".M"};
1037 for (auto suffix : suffixes) {
1038 if (file_path.ends_with_insensitive(suffix))
1039 return true;
1040 }
1041 return false;
1042}
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:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:214
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:313
A class that handles mangled names.
Definition: Mangled.h:33
ConstString GetDemangledName() const
Demangled name get accessor.
Definition: Mangled.cpp:262
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
std::string GetFullNameWithoutCategory() const
Creates a variation of this method without the category.
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.
llvm::StringRef GetCategory() const
Returns a reference to the category name.
llvm::StringRef GetClassName() const
Returns a reference to the class name.
static std::optional< const MethodName > Create(llvm::StringRef name, bool strict)
The static factory method for creating a MethodName.
llvm::StringRef GetPluginName() override
Definition: ObjCLanguage.h:198
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 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:175
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)
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:307
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:779
bool CMTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CoreMedia.cpp:22
template bool NSDataSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:45
SyntheticChildrenFrontEnd * NSArraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSArray.cpp:790
bool ObjCBOOLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:1128
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:223
bool NSBundleSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:39
bool NSIndexSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:234
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:29
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSException.cpp:99
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
template bool NSDictionarySummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
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.
template bool ObjCSELSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:278
bool NSArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSArray.cpp:335
void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char *string, llvm::StringRef type_name, TypeSummaryImpl::Flags flags, bool regex=false)
template bool NSDictionarySummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
template bool ObjCSELSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
SyntheticChildrenFrontEnd * NSSetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSSet.cpp:336
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:903
SyntheticChildrenFrontEnd * NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:139
bool NSMachPortSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:188
template bool NSDataSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSError_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSError.cpp:54
bool ObjCClassSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:1005
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:437
bool NSTimeZoneSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:90
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:33
SyntheticChildrenFrontEnd * NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
SyntheticChildrenFrontEnd * ObjCClassSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: Cocoa.cpp:1059
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:105
SyntheticChildrenFrontEnd * NSErrorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
Definition: NSError.cpp:189
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
Definition: lldb-forward.h:463
LanguageType
Programming language type.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
@ eFormatterMatchExact
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
Definition: lldb-forward.h:451
@ eNoDynamicValues
static bool IsClangType(const CompilerType &ct)
Definition: ClangUtil.cpp:17