LLDB  mainline
ObjCLanguage.cpp
Go to the documentation of this file.
1 //===-- ObjCLanguage.cpp ----------------------------------------*- C++ -*-===//
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 
14 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Target/Target.h"
23 
24 #include "llvm/Support/Threading.h"
25 
26 #include "CF.h"
27 #include "Cocoa.h"
28 #include "CoreMedia.h"
29 #include "NSDictionary.h"
30 #include "NSSet.h"
31 #include "NSString.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 using namespace lldb_private::formatters;
36 
37 void ObjCLanguage::Initialize() {
38  PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language",
39  CreateInstance);
40 }
41 
42 void ObjCLanguage::Terminate() {
43  PluginManager::UnregisterPlugin(CreateInstance);
44 }
45 
46 lldb_private::ConstString ObjCLanguage::GetPluginNameStatic() {
47  static ConstString g_name("objc");
48  return g_name;
49 }
50 
51 // PluginInterface protocol
52 
53 lldb_private::ConstString ObjCLanguage::GetPluginName() {
54  return GetPluginNameStatic();
55 }
56 
57 uint32_t ObjCLanguage::GetPluginVersion() { return 1; }
58 
59 // Static Functions
60 
61 Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) {
62  switch (language) {
64  return new ObjCLanguage();
65  default:
66  return nullptr;
67  }
68 }
69 
70 void ObjCLanguage::MethodName::Clear() {
71  m_full.Clear();
72  m_class.Clear();
73  m_category.Clear();
74  m_selector.Clear();
75  m_type = eTypeUnspecified;
76  m_category_is_valid = false;
77 }
78 
79 bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
80  Clear();
81  if (name.empty())
82  return IsValid(strict);
83 
84  // If "strict" is true. then the method must be specified with a '+' or '-'
85  // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
86  bool valid_prefix = false;
87 
88  if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
89  valid_prefix = name[1] == '[';
90  if (name[0] == '+')
91  m_type = eTypeClassMethod;
92  else
93  m_type = eTypeInstanceMethod;
94  } else if (!strict) {
95  // "strict" is false, the name just needs to start with '['
96  valid_prefix = name[0] == '[';
97  }
98 
99  if (valid_prefix) {
100  int name_len = name.size();
101  // Objective-C methods must have at least:
102  // "-[" or "+[" prefix
103  // One character for a class name
104  // One character for the space between the class name
105  // One character for the method name
106  // "]" suffix
107  if (name_len >= (5 + (strict ? 1 : 0)) && name.back() == ']') {
108  m_full.SetString(name);
109  }
110  }
111  return IsValid(strict);
112 }
113 
114 bool ObjCLanguage::MethodName::SetName(const char *name, bool strict) {
115  return SetName(llvm::StringRef(name), strict);
116 }
117 
118 ConstString ObjCLanguage::MethodName::GetClassName() {
119  if (!m_class) {
120  if (IsValid(false)) {
121  const char *full = m_full.GetCString();
122  const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
123  const char *paren_pos = strchr(class_start, '(');
124  if (paren_pos) {
125  m_class.SetCStringWithLength(class_start, paren_pos - class_start);
126  } else {
127  // No '(' was found in the full name, we can definitively say that our
128  // category was valid (and empty).
129  m_category_is_valid = true;
130  const char *space_pos = strchr(full, ' ');
131  if (space_pos) {
132  m_class.SetCStringWithLength(class_start, space_pos - class_start);
133  if (!m_class_category) {
134  // No category in name, so we can also fill in the m_class_category
135  m_class_category = m_class;
136  }
137  }
138  }
139  }
140  }
141  return m_class;
142 }
143 
144 ConstString ObjCLanguage::MethodName::GetClassNameWithCategory() {
145  if (!m_class_category) {
146  if (IsValid(false)) {
147  const char *full = m_full.GetCString();
148  const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
149  const char *space_pos = strchr(full, ' ');
150  if (space_pos) {
151  m_class_category.SetCStringWithLength(class_start,
152  space_pos - class_start);
153  // If m_class hasn't been filled in and the class with category doesn't
154  // contain a '(', then we can also fill in the m_class
155  if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) {
156  m_class = m_class_category;
157  // No '(' was found in the full name, we can definitively say that
158  // our category was valid (and empty).
159  m_category_is_valid = true;
160  }
161  }
162  }
163  }
164  return m_class_category;
165 }
166 
167 ConstString ObjCLanguage::MethodName::GetSelector() {
168  if (!m_selector) {
169  if (IsValid(false)) {
170  const char *full = m_full.GetCString();
171  const char *space_pos = strchr(full, ' ');
172  if (space_pos) {
173  ++space_pos; // skip the space
174  m_selector.SetCStringWithLength(space_pos, m_full.GetLength() -
175  (space_pos - full) - 1);
176  }
177  }
178  }
179  return m_selector;
180 }
181 
182 ConstString ObjCLanguage::MethodName::GetCategory() {
183  if (!m_category_is_valid && !m_category) {
184  if (IsValid(false)) {
185  m_category_is_valid = true;
186  const char *full = m_full.GetCString();
187  const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
188  const char *open_paren_pos = strchr(class_start, '(');
189  if (open_paren_pos) {
190  ++open_paren_pos; // Skip the open paren
191  const char *close_paren_pos = strchr(open_paren_pos, ')');
192  if (close_paren_pos)
193  m_category.SetCStringWithLength(open_paren_pos,
194  close_paren_pos - open_paren_pos);
195  }
196  }
197  }
198  return m_category;
199 }
200 
201 ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory(
202  bool empty_if_no_category) {
203  if (IsValid(false)) {
204  if (HasCategory()) {
205  StreamString strm;
206  if (m_type == eTypeClassMethod)
207  strm.PutChar('+');
208  else if (m_type == eTypeInstanceMethod)
209  strm.PutChar('-');
210  strm.Printf("[%s %s]", GetClassName().GetCString(),
211  GetSelector().GetCString());
212  return ConstString(strm.GetString());
213  }
214 
215  if (!empty_if_no_category) {
216  // Just return the full name since it doesn't have a category
217  return GetFullName();
218  }
219  }
220  return ConstString();
221 }
222 
223 size_t ObjCLanguage::MethodName::GetFullNames(std::vector<ConstString> &names,
224  bool append) {
225  if (!append)
226  names.clear();
227  if (IsValid(false)) {
228  StreamString strm;
229  const bool is_class_method = m_type == eTypeClassMethod;
230  const bool is_instance_method = m_type == eTypeInstanceMethod;
231  ConstString category = GetCategory();
232  if (is_class_method || is_instance_method) {
233  names.push_back(m_full);
234  if (category) {
235  strm.Printf("%c[%s %s]", is_class_method ? '+' : '-',
236  GetClassName().GetCString(), GetSelector().GetCString());
237  names.emplace_back(strm.GetString());
238  }
239  } else {
240  ConstString class_name = GetClassName();
241  ConstString selector = GetSelector();
242  strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
243  names.emplace_back(strm.GetString());
244  strm.Clear();
245  strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
246  names.emplace_back(strm.GetString());
247  strm.Clear();
248  if (category) {
249  strm.Printf("+[%s(%s) %s]", class_name.GetCString(),
250  category.GetCString(), selector.GetCString());
251  names.emplace_back(strm.GetString());
252  strm.Clear();
253  strm.Printf("-[%s(%s) %s]", class_name.GetCString(),
254  category.GetCString(), selector.GetCString());
255  names.emplace_back(strm.GetString());
256  }
257  }
258  }
259  return names.size();
260 }
261 
262 static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
263  if (!objc_category_sp)
264  return;
265 
266  TypeSummaryImpl::Flags objc_flags;
267  objc_flags.SetCascades(false)
268  .SetSkipPointers(true)
269  .SetSkipReferences(true)
270  .SetDontShowChildren(true)
271  .SetDontShowValue(true)
272  .SetShowMembersOneLiner(false)
273  .SetHideItemNames(false);
274 
275  lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(
277  objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
278  ObjC_BOOL_summary);
279  objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
280  ObjC_BOOL_summary);
281  objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
282  ObjC_BOOL_summary);
283 
284  // we need to skip pointers here since we are special casing a SEL* when
285  // retrieving its value
286  objc_flags.SetSkipPointers(true);
287  AddCXXSummary(objc_category_sp,
289  "SEL summary provider", ConstString("SEL"), objc_flags);
292  "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
295  "SEL summary provider", ConstString("objc_selector"), objc_flags);
298  "SEL summary provider", ConstString("objc_selector *"), objc_flags);
299  AddCXXSummary(objc_category_sp,
301  "SEL summary provider", ConstString("SEL *"), objc_flags);
302 
303  AddCXXSummary(objc_category_sp,
305  "Class summary provider", ConstString("Class"), objc_flags);
306 
307  SyntheticChildren::Flags class_synth_flags;
308  class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
309  false);
310 
311  AddCXXSynthetic(objc_category_sp,
313  "Class synthetic children", ConstString("Class"),
314  class_synth_flags);
315 
316  objc_flags.SetSkipPointers(false);
317  objc_flags.SetCascades(true);
318  objc_flags.SetSkipReferences(false);
319 
320  AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}",
321  ConstString("__block_literal_generic"), objc_flags);
322 
323  AddStringSummary(objc_category_sp, "${var.years} years, ${var.months} "
324  "months, ${var.days} days, ${var.hours} "
325  "hours, ${var.minutes} minutes "
326  "${var.seconds} seconds",
327  ConstString("CFGregorianUnits"), objc_flags);
328  AddStringSummary(objc_category_sp,
329  "location=${var.location} length=${var.length}",
330  ConstString("CFRange"), objc_flags);
331 
332  AddStringSummary(objc_category_sp,
333  "location=${var.location}, length=${var.length}",
334  ConstString("NSRange"), objc_flags);
335  AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...",
336  ConstString("NSRectArray"), objc_flags);
337 
338  AddOneLineSummary(objc_category_sp, ConstString("NSPoint"), objc_flags);
339  AddOneLineSummary(objc_category_sp, ConstString("NSSize"), objc_flags);
340  AddOneLineSummary(objc_category_sp, ConstString("NSRect"), objc_flags);
341 
342  AddOneLineSummary(objc_category_sp, ConstString("CGSize"), objc_flags);
343  AddOneLineSummary(objc_category_sp, ConstString("CGPoint"), objc_flags);
344  AddOneLineSummary(objc_category_sp, ConstString("CGRect"), objc_flags);
345 
346  AddStringSummary(objc_category_sp,
347  "red=${var.red} green=${var.green} blue=${var.blue}",
348  ConstString("RGBColor"), objc_flags);
350  objc_category_sp,
351  "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
352  ConstString("Rect"), objc_flags);
353  AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}",
354  ConstString("Point"), objc_flags);
355  AddStringSummary(objc_category_sp,
356  "${var.month}/${var.day}/${var.year} ${var.hour} "
357  ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
358  ConstString("DateTimeRect *"), objc_flags);
359  AddStringSummary(objc_category_sp, "${var.ld.month}/${var.ld.day}/"
360  "${var.ld.year} ${var.ld.hour} "
361  ":${var.ld.minute} :${var.ld.second} "
362  "dayOfWeek:${var.ld.dayOfWeek}",
363  ConstString("LongDateRect"), objc_flags);
364  AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})",
365  ConstString("HIPoint"), objc_flags);
366  AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}",
367  ConstString("HIRect"), objc_flags);
368 
369  TypeSummaryImpl::Flags appkit_flags;
370  appkit_flags.SetCascades(true)
371  .SetSkipPointers(false)
372  .SetSkipReferences(false)
373  .SetDontShowChildren(true)
374  .SetDontShowValue(false)
375  .SetShowMembersOneLiner(false)
376  .SetHideItemNames(false);
377 
378  appkit_flags.SetDontShowChildren(false);
379 
382  "NSArray summary provider", ConstString("NSArray"), appkit_flags);
385  "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
388  "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
391  "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
392  AddCXXSummary(objc_category_sp,
394  "NSArray summary provider",
395  ConstString("__NSSingleObjectArrayI"), appkit_flags);
398  "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
401  "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
404  "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags);
407  "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
408  AddCXXSummary(objc_category_sp,
410  "NSArray summary provider", ConstString("CFMutableArrayRef"),
411  appkit_flags);
412 
413  AddCXXSummary(objc_category_sp,
415  "NSDictionary summary provider", ConstString("NSDictionary"),
416  appkit_flags);
417  AddCXXSummary(objc_category_sp,
419  "NSDictionary summary provider",
420  ConstString("NSMutableDictionary"), appkit_flags);
421  AddCXXSummary(objc_category_sp,
423  "NSDictionary summary provider",
424  ConstString("__NSCFDictionary"), appkit_flags);
425  AddCXXSummary(objc_category_sp,
427  "NSDictionary summary provider", ConstString("__NSDictionaryI"),
428  appkit_flags);
429  AddCXXSummary(objc_category_sp,
431  "NSDictionary summary provider",
432  ConstString("__NSSingleEntryDictionaryI"), appkit_flags);
433  AddCXXSummary(objc_category_sp,
435  "NSDictionary summary provider", ConstString("__NSDictionaryM"),
436  appkit_flags);
437  AddCXXSummary(objc_category_sp,
439  "NSDictionary summary provider", ConstString("CFDictionaryRef"),
440  appkit_flags);
441  AddCXXSummary(objc_category_sp,
443  "NSDictionary summary provider",
444  ConstString("CFMutableDictionaryRef"), appkit_flags);
445 
446  AddCXXSummary(objc_category_sp,
447  lldb_private::formatters::NSSetSummaryProvider<false>,
448  "NSSet summary", ConstString("NSSet"), appkit_flags);
450  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
451  "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
452  AddCXXSummary(objc_category_sp,
453  lldb_private::formatters::NSSetSummaryProvider<true>,
454  "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
456  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>,
457  "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
458  AddCXXSummary(objc_category_sp,
459  lldb_private::formatters::NSSetSummaryProvider<false>,
460  "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
461  AddCXXSummary(objc_category_sp,
462  lldb_private::formatters::NSSetSummaryProvider<false>,
463  "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
464  AddCXXSummary(objc_category_sp,
465  lldb_private::formatters::NSSetSummaryProvider<false>,
466  "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
468  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
469  "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
471  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
472  "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
474  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
475  "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
477  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
478  "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
480  objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>,
481  "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
482 
485  "NSError summary provider", ConstString("NSError"), appkit_flags);
488  "NSException summary provider", ConstString("NSException"), appkit_flags);
489 
490  // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}",
491  // ConstString("$_lldb_typegen_nspair"), appkit_flags);
492 
493  appkit_flags.SetDontShowChildren(true);
494 
495  AddCXXSynthetic(objc_category_sp,
497  "NSArray synthetic children", ConstString("__NSArrayM"),
498  ScriptedSyntheticChildren::Flags());
499  AddCXXSynthetic(objc_category_sp,
501  "NSArray synthetic children", ConstString("__NSArrayI"),
502  ScriptedSyntheticChildren::Flags());
503  AddCXXSynthetic(objc_category_sp,
505  "NSArray synthetic children", ConstString("__NSArray0"),
506  ScriptedSyntheticChildren::Flags());
507  AddCXXSynthetic(objc_category_sp,
509  "NSArray synthetic children",
510  ConstString("__NSSingleObjectArrayI"),
511  ScriptedSyntheticChildren::Flags());
512  AddCXXSynthetic(objc_category_sp,
514  "NSArray synthetic children", ConstString("NSArray"),
515  ScriptedSyntheticChildren::Flags());
516  AddCXXSynthetic(objc_category_sp,
518  "NSArray synthetic children", ConstString("NSMutableArray"),
519  ScriptedSyntheticChildren::Flags());
520  AddCXXSynthetic(objc_category_sp,
522  "NSArray synthetic children", ConstString("__NSCFArray"),
523  ScriptedSyntheticChildren::Flags());
524  AddCXXSynthetic(objc_category_sp,
526  "NSArray synthetic children", ConstString("_NSCallStackArray"),
527  ScriptedSyntheticChildren::Flags());
528  AddCXXSynthetic(objc_category_sp,
530  "NSArray synthetic children",
531  ConstString("CFMutableArrayRef"),
532  ScriptedSyntheticChildren::Flags());
533  AddCXXSynthetic(objc_category_sp,
535  "NSArray synthetic children", ConstString("CFArrayRef"),
536  ScriptedSyntheticChildren::Flags());
537 
539  objc_category_sp,
541  "NSDictionary synthetic children", ConstString("__NSDictionaryM"),
542  ScriptedSyntheticChildren::Flags());
544  objc_category_sp,
546  "NSDictionary synthetic children", ConstString("__NSDictionaryI"),
547  ScriptedSyntheticChildren::Flags());
549  objc_category_sp,
551  "NSDictionary synthetic children",
552  ConstString("__NSSingleEntryDictionaryI"),
553  ScriptedSyntheticChildren::Flags());
555  objc_category_sp,
557  "NSDictionary synthetic children", ConstString("__NSCFDictionary"),
558  ScriptedSyntheticChildren::Flags());
560  objc_category_sp,
562  "NSDictionary synthetic children", ConstString("NSDictionary"),
563  ScriptedSyntheticChildren::Flags());
565  objc_category_sp,
567  "NSDictionary synthetic children", ConstString("NSMutableDictionary"),
568  ScriptedSyntheticChildren::Flags());
570  objc_category_sp,
572  "NSDictionary synthetic children", ConstString("CFDictionaryRef"),
573  ScriptedSyntheticChildren::Flags());
575  objc_category_sp,
577  "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"),
578  ScriptedSyntheticChildren::Flags());
579 
580  AddCXXSynthetic(objc_category_sp,
582  "NSError synthetic children", ConstString("NSError"),
583  ScriptedSyntheticChildren::Flags());
584  AddCXXSynthetic(objc_category_sp,
586  "NSException synthetic children", ConstString("NSException"),
587  ScriptedSyntheticChildren::Flags());
588 
589  AddCXXSynthetic(objc_category_sp,
591  "NSSet synthetic children", ConstString("NSSet"),
592  ScriptedSyntheticChildren::Flags());
593  AddCXXSynthetic(objc_category_sp,
595  "__NSSetI synthetic children", ConstString("__NSSetI"),
596  ScriptedSyntheticChildren::Flags());
597  AddCXXSynthetic(objc_category_sp,
599  "__NSSetM synthetic children", ConstString("__NSSetM"),
600  ScriptedSyntheticChildren::Flags());
603  "NSMutableSet synthetic children", ConstString("NSMutableSet"),
604  ScriptedSyntheticChildren::Flags());
607  "NSOrderedSet synthetic children", ConstString("NSOrderedSet"),
608  ScriptedSyntheticChildren::Flags());
611  "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"),
612  ScriptedSyntheticChildren::Flags());
615  "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"),
616  ScriptedSyntheticChildren::Flags());
617 
618  AddCXXSynthetic(objc_category_sp,
620  "NSIndexPath synthetic children", ConstString("NSIndexPath"),
621  ScriptedSyntheticChildren::Flags());
622 
625  "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
626  AddCXXSummary(objc_category_sp,
628  "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
629  AddCXXSummary(objc_category_sp,
631  "CFBag summary provider", ConstString("const struct __CFBag"),
632  appkit_flags);
635  "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
636 
637  AddCXXSummary(objc_category_sp,
639  "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"),
640  appkit_flags);
641  AddCXXSummary(objc_category_sp,
643  "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"),
644  appkit_flags);
645 
648  "NSString summary provider", ConstString("NSString"), appkit_flags);
651  "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
654  "NSString summary provider", ConstString("__CFString"), appkit_flags);
655  AddCXXSummary(objc_category_sp,
657  "NSString summary provider", ConstString("CFMutableStringRef"),
658  appkit_flags);
659  AddCXXSummary(objc_category_sp,
661  "NSString summary provider", ConstString("NSMutableString"),
662  appkit_flags);
663  AddCXXSummary(objc_category_sp,
665  "NSString summary provider",
666  ConstString("__NSCFConstantString"), appkit_flags);
669  "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
670  AddCXXSummary(objc_category_sp,
672  "NSString summary provider", ConstString("NSCFConstantString"),
673  appkit_flags);
676  "NSString summary provider", ConstString("NSCFString"), appkit_flags);
679  "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
680  AddCXXSummary(objc_category_sp,
682  "NSString summary provider",
683  ConstString("NSTaggedPointerString"), appkit_flags);
684 
685  AddCXXSummary(objc_category_sp,
687  "NSAttributedString summary provider",
688  ConstString("NSAttributedString"), appkit_flags);
690  objc_category_sp,
692  "NSMutableAttributedString summary provider",
693  ConstString("NSMutableAttributedString"), appkit_flags);
695  objc_category_sp,
697  "NSMutableAttributedString summary provider",
698  ConstString("NSConcreteMutableAttributedString"), appkit_flags);
699 
702  "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
703 
704  AddCXXSummary(objc_category_sp,
706  "NSData summary provider", ConstString("NSData"), appkit_flags);
709  "NSData summary provider", ConstString("_NSInlineData"), appkit_flags);
712  "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
713  AddCXXSummary(objc_category_sp,
715  "NSData summary provider", ConstString("NSConcreteMutableData"),
716  appkit_flags);
719  "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
722  "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
725  "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
728  "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
729 
732  "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
733 
734  AddCXXSummary(objc_category_sp,
736  "NSNotification summary provider",
737  ConstString("NSNotification"), appkit_flags);
738  AddCXXSummary(objc_category_sp,
740  "NSNotification summary provider",
741  ConstString("NSConcreteNotification"), appkit_flags);
742 
745  "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
748  "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
751  "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
754  "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
757  "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
760  "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
761  AddCXXSummary(objc_category_sp,
763  "NSDecimalNumber summary provider",
764  ConstString("NSDecimalNumber"), appkit_flags);
765 
766  AddCXXSummary(objc_category_sp,
768  "NSURL summary provider", ConstString("NSURL"), appkit_flags);
771  "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
772 
773  AddCXXSummary(objc_category_sp,
775  "NSDate summary provider", ConstString("NSDate"), appkit_flags);
778  "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
781  "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
784  "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
785 
788  "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
789  AddCXXSummary(objc_category_sp,
791  "NSTimeZone summary provider", ConstString("CFTimeZoneRef"),
792  appkit_flags);
795  "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
796 
797  // CFAbsoluteTime is actually a double rather than a pointer to an object we
798  // do not care about the numeric value, since it is probably meaningless to
799  // users
800  appkit_flags.SetDontShowValue(true);
801  AddCXXSummary(objc_category_sp,
803  "CFAbsoluteTime summary provider",
804  ConstString("CFAbsoluteTime"), appkit_flags);
805  appkit_flags.SetDontShowValue(false);
806 
809  "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
810  AddCXXSummary(objc_category_sp,
812  "NSIndexSet summary provider", ConstString("NSMutableIndexSet"),
813  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  ConstString("CFGregorianDate"), appkit_flags);
819 
820  AddCXXSummary(objc_category_sp,
822  "CFBitVector summary provider", ConstString("CFBitVectorRef"),
823  appkit_flags);
824  AddCXXSummary(objc_category_sp,
826  "CFBitVector summary provider",
827  ConstString("CFMutableBitVectorRef"), appkit_flags);
828  AddCXXSummary(objc_category_sp,
830  "CFBitVector summary provider", ConstString("__CFBitVector"),
831  appkit_flags);
832  AddCXXSummary(objc_category_sp,
834  "CFBitVector summary provider",
835  ConstString("__CFMutableBitVector"), appkit_flags);
836 }
837 
838 static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) {
839  if (!objc_category_sp)
840  return;
841 
842  TypeSummaryImpl::Flags cm_flags;
843  cm_flags.SetCascades(true)
844  .SetDontShowChildren(false)
845  .SetDontShowValue(false)
846  .SetHideItemNames(false)
847  .SetShowMembersOneLiner(false)
848  .SetSkipPointers(false)
849  .SetSkipReferences(false);
850 
851  AddCXXSummary(objc_category_sp,
853  "CMTime summary provider", ConstString("CMTime"), cm_flags);
854 }
855 
856 lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() {
857  static llvm::once_flag g_initialize;
858  static TypeCategoryImplSP g_category;
859 
860  llvm::call_once(g_initialize, [this]() -> void {
861  DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
862  if (g_category) {
863  LoadCoreMediaFormatters(g_category);
864  LoadObjCFormatters(g_category);
865  }
866  });
867  return g_category;
868 }
869 
870 std::vector<ConstString>
871 ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj,
872  lldb::DynamicValueType use_dynamic) {
873  std::vector<ConstString> result;
874 
875  if (use_dynamic == lldb::eNoDynamicValues)
876  return result;
877 
878  CompilerType compiler_type(valobj.GetCompilerType());
879 
880  const bool check_cpp = false;
881  const bool check_objc = true;
882  bool canBeObjCDynamic =
883  compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
884 
885  if (canBeObjCDynamic) {
886  do {
887  lldb::ProcessSP process_sp = valobj.GetProcessSP();
888  if (!process_sp)
889  break;
890  ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime();
891  if (runtime == nullptr)
892  break;
894  runtime->GetClassDescriptor(valobj));
895  if (!objc_class_sp)
896  break;
897  if (ConstString name = objc_class_sp->GetClassName())
898  result.push_back(name);
899  } while (false);
900  }
901 
902  return result;
903 }
904 
905 std::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  Process *process = exe_scope->CalculateProcess().get();
933  if (process) {
934  const bool create_on_demand = false;
935  auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);
936  if (objc_runtime) {
937  auto decl_vendor = objc_runtime->GetDeclVendor();
938  if (decl_vendor) {
939  std::vector<clang::NamedDecl *> decls;
940  ConstString name(key);
941  decl_vendor->FindDecls(name, true, UINT32_MAX, decls);
942  for (auto decl : decls) {
943  if (decl) {
944  if (CompilerType candidate =
945  ClangASTContext::GetTypeForDecl(decl)) {
946  result = true;
947  std::unique_ptr<Language::TypeScavenger::Result> result(
948  new ObjCScavengerResult(candidate));
949  results.insert(std::move(result));
950  }
951  }
952  }
953  }
954  }
955  }
956 
957  return result;
958  }
959 
960  friend class lldb_private::ObjCLanguage;
961  };
962 
963  class ObjCModulesScavenger : public Language::TypeScavenger {
964  protected:
965  bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
966  ResultSet &results) override {
967  bool result = false;
968 
969  Target *target = exe_scope->CalculateTarget().get();
970  if (target) {
971  if (auto clang_modules_decl_vendor =
972  target->GetClangModulesDeclVendor()) {
973  std::vector<clang::NamedDecl *> decls;
974  ConstString key_cs(key);
975 
976  if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX,
977  decls) > 0 &&
978  !decls.empty()) {
979  CompilerType module_type =
980  ClangASTContext::GetTypeForDecl(decls.front());
981  result = true;
982  std::unique_ptr<Language::TypeScavenger::Result> result(
983  new ObjCScavengerResult(module_type));
984  results.insert(std::move(result));
985  }
986  }
987  }
988 
989  return result;
990  }
991 
992  friend class lldb_private::ObjCLanguage;
993  };
994 
995  class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger {
996  public:
997  CompilerType AdjustForInclusion(CompilerType &candidate) override {
998  LanguageType lang_type(candidate.GetMinimumLanguage());
999  if (!Language::LanguageIsObjC(lang_type))
1000  return CompilerType();
1001  if (candidate.IsTypedefType())
1002  return candidate.GetTypedefedType();
1003  return candidate;
1004  }
1005  };
1006 
1007  return std::unique_ptr<TypeScavenger>(
1008  new Language::EitherTypeScavenger<ObjCModulesScavenger,
1009  ObjCRuntimeScavenger,
1010  ObjCDebugInfoScavenger>());
1011 }
1012 
1013 bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj,
1014  ConstString type_hint,
1015  std::string &prefix,
1016  std::string &suffix) {
1017  static ConstString g_CFBag("CFBag");
1018  static ConstString g_CFBinaryHeap("CFBinaryHeap");
1019 
1020  static ConstString g_NSNumberChar("NSNumber:char");
1021  static ConstString g_NSNumberShort("NSNumber:short");
1022  static ConstString g_NSNumberInt("NSNumber:int");
1023  static ConstString g_NSNumberLong("NSNumber:long");
1024  static ConstString g_NSNumberInt128("NSNumber:int128_t");
1025  static ConstString g_NSNumberFloat("NSNumber:float");
1026  static ConstString g_NSNumberDouble("NSNumber:double");
1027 
1028  static ConstString g_NSData("NSData");
1029  static ConstString g_NSArray("NSArray");
1030  static ConstString g_NSString("NSString");
1031  static ConstString g_NSStringStar("NSString*");
1032 
1033  if (type_hint.IsEmpty())
1034  return false;
1035 
1036  prefix.clear();
1037  suffix.clear();
1038 
1039  if (type_hint == g_CFBag || type_hint == g_CFBinaryHeap) {
1040  prefix = "@";
1041  return true;
1042  }
1043 
1044  if (type_hint == g_NSNumberChar) {
1045  prefix = "(char)";
1046  return true;
1047  }
1048  if (type_hint == g_NSNumberShort) {
1049  prefix = "(short)";
1050  return true;
1051  }
1052  if (type_hint == g_NSNumberInt) {
1053  prefix = "(int)";
1054  return true;
1055  }
1056  if (type_hint == g_NSNumberLong) {
1057  prefix = "(long)";
1058  return true;
1059  }
1060  if (type_hint == g_NSNumberInt128) {
1061  prefix = "(int128_t)";
1062  return true;
1063  }
1064  if (type_hint == g_NSNumberFloat) {
1065  prefix = "(float)";
1066  return true;
1067  }
1068  if (type_hint == g_NSNumberDouble) {
1069  prefix = "(double)";
1070  return true;
1071  }
1072 
1073  if (type_hint == g_NSData || type_hint == g_NSArray) {
1074  prefix = "@\"";
1075  suffix = "\"";
1076  return true;
1077  }
1078 
1079  if (type_hint == g_NSString || type_hint == g_NSStringStar) {
1080  prefix = "@";
1081  return true;
1082  }
1083 
1084  return false;
1085 }
1086 
1087 bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
1088  const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
1089  bool isObjCpointer =
1090  (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
1091  if (!isObjCpointer)
1092  return false;
1093  bool canReadValue = true;
1094  bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
1095  return canReadValue && isZero;
1096 }
1097 
1098 bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
1099  const auto suffixes = {".h", ".m", ".M"};
1100  for (auto suffix : suffixes) {
1101  if (file_path.endswith_lower(suffix))
1102  return true;
1103  }
1104  return false;
1105 }
bool CFBitVectorSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:111
CompilerType GetCompilerType()
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
Flags & SetCascades(bool value=true)
Definition: TypeSummary.h:85
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
bool NSBundleSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:40
template bool NSDictionarySummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSMutableAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:329
bool NSIndexSetSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:232
Flags & SetHideItemNames(bool value=true)
Definition: TypeSummary.h:176
bool NSDateSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:792
template bool NSDataSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
Flags & SetSkipReferences(bool value=true)
virtual lldb::ProcessSP CalculateProcess()=0
void AddOneLineSummary(TypeCategoryImpl::SharedPointer category_sp, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
template bool ObjCSELSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:423
template bool ObjCSELSummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
SyntheticChildrenFrontEnd * NSExceptionSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
virtual ObjCLanguageRuntime * GetObjCLanguageRuntime(bool retry_if_null=true)
Definition: Process.cpp:1573
bool NSError_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSError.cpp:55
template bool NSDataSummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
virtual lldb::TargetSP CalculateTarget()=0
Flags & SetCascades(bool value=true)
void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char *string, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
bool NSURLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:676
SyntheticChildrenFrontEnd * NSSetSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSSet.cpp:302
#define UINT32_MAX
Definition: lldb-defines.h:31
SyntheticChildrenFrontEnd * NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
LanguageType
Programming language type.
lldb::LanguageType GetMinimumLanguage()
Flags & SetDontShowValue(bool value=true)
Definition: TypeSummary.h:150
bool NSMachPortSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:184
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
Flags & SetSkipPointers(bool value=true)
Flags & SetSkipPointers(bool value=true)
Definition: TypeSummary.h:98
bool NSArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSArray.cpp:339
llvm::StringRef GetString() const
bool NSTimeZoneSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:90
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
bool NSStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:53
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
SyntheticChildrenFrontEnd * NSArraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: NSArray.cpp:793
void AddCXXSummary(TypeCategoryImpl::SharedPointer category_sp, CXXFunctionSummaryFormat::Callback funct, const char *description, ConstString type_name, TypeSummaryImpl::Flags flags, bool regex=false)
bool NSException_SummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSException.cpp:97
size_t PutChar(char ch)
Definition: Stream.cpp:103
Flags & SetDontShowChildren(bool value=true)
Definition: TypeSummary.h:124
SyntheticChildrenFrontEnd * ObjCClassSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: Cocoa.cpp:944
A uniqued constant string class.
Definition: ConstString.h:38
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
SyntheticChildrenFrontEnd * NSErrorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
Definition: NSError.cpp:185
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:361
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
bool CFAbsoluteTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:29
Definition: SBAddress.h:15
CompilerType GetTypedefedType() const
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
bool ObjCClassSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:889
Flags & SetSkipReferences(bool value=true)
Definition: TypeSummary.h:111
bool CFBinaryHeapSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:231
Flags & SetShowMembersOneLiner(bool value=true)
Definition: TypeSummary.h:163
bool IsPossibleDynamicType(CompilerType *target_type, bool check_cplusplus, bool check_objc) const
ClangModulesDeclVendor * GetClangModulesDeclVendor()
Definition: Target.cpp:2488
template bool NSDictionarySummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:340
bool NSAttributedStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: NSString.cpp:300
bool CFBagSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CF.cpp:45
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:137
SyntheticChildrenFrontEnd * NSIndexPathSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
void AddCXXSynthetic(TypeCategoryImpl::SharedPointer category_sp, CXXSyntheticChildren::CreateFrontEndCallback generator, const char *description, ConstString type_name, ScriptedSyntheticChildren::Flags flags, bool regex=false)
bool ObjCBOOLSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: Cocoa.cpp:1015
bool CMTimeSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: CoreMedia.cpp:22