diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp new file mode 100644 index 000000000000..742ae7b14945 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -0,0 +1,1042 @@ +//===-- ObjCLanguage.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <mutex> + +#include "ObjCLanguage.h" + +#include "Plugins/ExpressionParser/Clang/ClangUtil.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/Support/Threading.h" + +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" + +#include "CF.h" +#include "Cocoa.h" +#include "CoreMedia.h" +#include "NSDictionary.h" +#include "NSSet.h" +#include "NSString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +LLDB_PLUGIN_DEFINE(ObjCLanguage) + +void ObjCLanguage::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C Language", + CreateInstance); +} + +void ObjCLanguage::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +// Static Functions + +Language *ObjCLanguage::CreateInstance(lldb::LanguageType language) { + switch (language) { + case lldb::eLanguageTypeObjC: + return new ObjCLanguage(); + default: + return nullptr; + } +} + +std::optional<const ObjCLanguage::MethodName> +ObjCLanguage::MethodName::Create(llvm::StringRef name, bool strict) { + if (name.empty()) + return std::nullopt; + + // Objective-C method minimum requirements: + // - If `strict` is true, must start with '-' or '+' (1 char) + // - Must be followed by '[' (1 char) + // - Must have at least one character for class name (1 char) + // - Must have a space between class name and method name (1 char) + // - Must have at least one character for method name (1 char) + // - Must be end with ']' (1 char) + // This means that the minimum size is 5 characters (6 if `strict`) + // e.g. [a a] (-[a a] or +[a a] if `strict`) + + // We can check length and ending invariants first + if (name.size() < (5 + (strict ? 1 : 0)) || name.back() != ']') + return std::nullopt; + + // Figure out type + Type type = eTypeUnspecified; + if (name.starts_with("+[")) + type = eTypeClassMethod; + else if (name.starts_with("-[")) + type = eTypeInstanceMethod; + + // If there's no type and it's strict, this is invalid + if (strict && type == eTypeUnspecified) + return std::nullopt; + + // If not strict and type unspecified, make sure we start with '[' + if (type == eTypeUnspecified && name.front() != '[') + return std::nullopt; + + // If we've gotten here, we're confident that this looks enough like an + // Objective-C method to treat it like one. + ObjCLanguage::MethodName method_name(name, type); + return method_name; +} + +llvm::StringRef ObjCLanguage::MethodName::GetClassName() const { + llvm::StringRef full = m_full; + const size_t class_start_pos = (full.front() == '[' ? 1 : 2); + const size_t paren_pos = full.find('(', class_start_pos); + // If there's a category we want to stop there + if (paren_pos != llvm::StringRef::npos) + return full.substr(class_start_pos, paren_pos - class_start_pos); + + // Otherwise we find the space separating the class and method + const size_t space_pos = full.find(' ', class_start_pos); + return full.substr(class_start_pos, space_pos - class_start_pos); +} + +llvm::StringRef ObjCLanguage::MethodName::GetClassNameWithCategory() const { + llvm::StringRef full = m_full; + const size_t class_start_pos = (full.front() == '[' ? 1 : 2); + const size_t space_pos = full.find(' ', class_start_pos); + return full.substr(class_start_pos, space_pos - class_start_pos); +} + +llvm::StringRef ObjCLanguage::MethodName::GetSelector() const { + llvm::StringRef full = m_full; + const size_t space_pos = full.find(' '); + if (space_pos == llvm::StringRef::npos) + return llvm::StringRef(); + const size_t closing_bracket = full.find(']', space_pos); + return full.substr(space_pos + 1, closing_bracket - space_pos - 1); +} + +llvm::StringRef ObjCLanguage::MethodName::GetCategory() const { + llvm::StringRef full = m_full; + const size_t open_paren_pos = full.find('('); + const size_t close_paren_pos = full.find(')'); + + if (open_paren_pos == llvm::StringRef::npos || + close_paren_pos == llvm::StringRef::npos) + return llvm::StringRef(); + + return full.substr(open_paren_pos + 1, + close_paren_pos - (open_paren_pos + 1)); +} + +std::string ObjCLanguage::MethodName::GetFullNameWithoutCategory() const { + llvm::StringRef full = m_full; + const size_t open_paren_pos = full.find('('); + const size_t close_paren_pos = full.find(')'); + if (open_paren_pos == llvm::StringRef::npos || + close_paren_pos == llvm::StringRef::npos) + return std::string(); + + llvm::StringRef class_name = GetClassName(); + llvm::StringRef selector_name = GetSelector(); + + // Compute the total size to avoid reallocations + // class name + selector name + '[' + ' ' + ']' + size_t total_size = class_name.size() + selector_name.size() + 3; + if (m_type != eTypeUnspecified) + total_size++; // For + or - + + std::string name_sans_category; + name_sans_category.reserve(total_size); + + if (m_type == eTypeClassMethod) + name_sans_category += '+'; + else if (m_type == eTypeInstanceMethod) + name_sans_category += '-'; + + name_sans_category += '['; + name_sans_category.append(class_name.data(), class_name.size()); + name_sans_category += ' '; + name_sans_category.append(selector_name.data(), selector_name.size()); + name_sans_category += ']'; + + return name_sans_category; +} + +std::vector<Language::MethodNameVariant> +ObjCLanguage::GetMethodNameVariants(ConstString method_name) const { + std::vector<Language::MethodNameVariant> variant_names; + std::optional<const ObjCLanguage::MethodName> objc_method = + ObjCLanguage::MethodName::Create(method_name.GetStringRef(), false); + if (!objc_method) + return variant_names; + + variant_names.emplace_back(ConstString(objc_method->GetSelector()), + lldb::eFunctionNameTypeSelector); + + const std::string name_sans_category = + objc_method->GetFullNameWithoutCategory(); + + if (objc_method->IsClassMethod() || objc_method->IsInstanceMethod()) { + if (!name_sans_category.empty()) + variant_names.emplace_back(ConstString(name_sans_category.c_str()), + lldb::eFunctionNameTypeFull); + } else { + StreamString strm; + + strm.Printf("+%s", objc_method->GetFullName().c_str()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); + strm.Clear(); + + strm.Printf("-%s", objc_method->GetFullName().c_str()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); + strm.Clear(); + + if (!name_sans_category.empty()) { + strm.Printf("+%s", name_sans_category.c_str()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); + strm.Clear(); + + strm.Printf("-%s", name_sans_category.c_str()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); + } + } + + return variant_names; +} + +bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const { + ConstString demangled_name = mangled.GetDemangledName(); + if (!demangled_name) + return false; + return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()); +} + +static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { + if (!objc_category_sp) + return; + + TypeSummaryImpl::Flags objc_flags; + objc_flags.SetCascades(false) + .SetSkipPointers(true) + .SetSkipReferences(true) + .SetDontShowChildren(true) + .SetDontShowValue(true) + .SetShowMembersOneLiner(false) + .SetHideItemNames(false); + + lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat( + objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider, "")); + objc_category_sp->AddTypeSummary("BOOL", eFormatterMatchExact, + ObjC_BOOL_summary); + objc_category_sp->AddTypeSummary("BOOL &", eFormatterMatchExact, + ObjC_BOOL_summary); + objc_category_sp->AddTypeSummary("BOOL *", eFormatterMatchExact, + ObjC_BOOL_summary); + + // we need to skip pointers here since we are special casing a SEL* when + // retrieving its value + objc_flags.SetSkipPointers(true); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCSELSummaryProvider<false>, + "SEL summary provider", "SEL", objc_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCSELSummaryProvider<false>, + "SEL summary provider", "struct objc_selector", objc_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCSELSummaryProvider<false>, + "SEL summary provider", "objc_selector", objc_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCSELSummaryProvider<true>, + "SEL summary provider", "objc_selector *", objc_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCSELSummaryProvider<true>, + "SEL summary provider", "SEL *", objc_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::ObjCClassSummaryProvider, + "Class summary provider", "Class", objc_flags); + + SyntheticChildren::Flags class_synth_flags; + class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( + false); + + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, + "Class synthetic children", "Class", class_synth_flags); + + objc_flags.SetSkipPointers(false); + objc_flags.SetCascades(true); + objc_flags.SetSkipReferences(false); + + AddStringSummary(objc_category_sp, "${var.__FuncPtr%A}", + "__block_literal_generic", objc_flags); + + AddStringSummary(objc_category_sp, + "${var.years} years, ${var.months} " + "months, ${var.days} days, ${var.hours} " + "hours, ${var.minutes} minutes " + "${var.seconds} seconds", + "CFGregorianUnits", objc_flags); + AddStringSummary(objc_category_sp, + "location=${var.location} length=${var.length}", "CFRange", + objc_flags); + + AddStringSummary(objc_category_sp, + "location=${var.location}, length=${var.length}", "NSRange", + objc_flags); + AddStringSummary(objc_category_sp, "(${var.origin}, ${var.size}), ...", + "NSRectArray", objc_flags); + + AddOneLineSummary(objc_category_sp, "NSPoint", objc_flags); + AddOneLineSummary(objc_category_sp, "NSSize", objc_flags); + AddOneLineSummary(objc_category_sp, "NSRect", objc_flags); + + AddOneLineSummary(objc_category_sp, "CGSize", objc_flags); + AddOneLineSummary(objc_category_sp, "CGPoint", objc_flags); + AddOneLineSummary(objc_category_sp, "CGRect", objc_flags); + + AddStringSummary(objc_category_sp, + "red=${var.red} green=${var.green} blue=${var.blue}", + "RGBColor", objc_flags); + AddStringSummary( + objc_category_sp, + "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", "Rect", + objc_flags); + AddStringSummary(objc_category_sp, "{(v=${var.v}, h=${var.h})}", "Point", + objc_flags); + AddStringSummary(objc_category_sp, + "${var.month}/${var.day}/${var.year} ${var.hour} " + ":${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}", + "DateTimeRect *", objc_flags); + AddStringSummary(objc_category_sp, + "${var.ld.month}/${var.ld.day}/" + "${var.ld.year} ${var.ld.hour} " + ":${var.ld.minute} :${var.ld.second} " + "dayOfWeek:${var.ld.dayOfWeek}", + "LongDateRect", objc_flags); + AddStringSummary(objc_category_sp, "(x=${var.x}, y=${var.y})", "HIPoint", + objc_flags); + AddStringSummary(objc_category_sp, "origin=${var.origin} size=${var.size}", + "HIRect", objc_flags); + + TypeSummaryImpl::Flags appkit_flags; + appkit_flags.SetCascades(true) + .SetSkipPointers(false) + .SetSkipReferences(false) + .SetDontShowChildren(true) + .SetDontShowValue(false) + .SetShowMembersOneLiner(false) + .SetHideItemNames(false); + + appkit_flags.SetDontShowChildren(false); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "NSArray", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "NSConstantArray", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "NSMutableArray", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "__NSArrayI", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "__NSArray0", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "__NSSingleObjectArrayI", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "__NSArrayM", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "__NSCFArray", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "_NSCallStackArray", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "CFArrayRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", "CFMutableArrayRef", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "NSDictionary", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "NSConstantDictionary", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "NSMutableDictionary", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "__NSCFDictionary", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "__NSDictionaryI", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "__NSSingleEntryDictionaryI", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<false>, + "NSDictionary summary provider", "__NSDictionaryM", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<true>, + "NSDictionary summary provider", "CFDictionaryRef", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<true>, + "NSDictionary summary provider", "__CFDictionary", + appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDictionarySummaryProvider<true>, + "NSDictionary summary provider", "CFMutableDictionaryRef", + appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "NSSet summary", "NSSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "NSMutableSet summary", "NSMutableSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<true>, + "CFSetRef summary", "CFSetRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<true>, + "CFMutableSetRef summary", "CFMutableSetRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__NSCFSet summary", "__NSCFSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__CFSet summary", "__CFSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__NSSetI summary", "__NSSetI", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__NSSetM summary", "__NSSetM", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "NSCountedSet summary", "NSCountedSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "NSMutableSet summary", "NSMutableSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "NSOrderedSet summary", "NSOrderedSet", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__NSOrderedSetI summary", "__NSOrderedSetI", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSSetSummaryProvider<false>, + "__NSOrderedSetM summary", "__NSOrderedSetM", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSError_SummaryProvider, + "NSError summary provider", "NSError", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSException_SummaryProvider, + "NSException summary provider", "NSException", appkit_flags); + + // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", + // ConstString("$_lldb_typegen_nspair"), appkit_flags); + + appkit_flags.SetDontShowChildren(true); + + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "__NSArrayM", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "__NSArrayI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "__NSArray0", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "__NSSingleObjectArrayI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "NSArray", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "NSConstantArray", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "NSMutableArray", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "__NSCFArray", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "_NSCallStackArray", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "CFMutableArrayRef", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", "CFArrayRef", + ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "__NSDictionaryM", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "NSConstantDictionary", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "__NSDictionaryI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "__NSSingleEntryDictionaryI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "__NSCFDictionary", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "NSDictionary", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "NSMutableDictionary", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "CFDictionaryRef", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "CFMutableDictionaryRef", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic( + objc_category_sp, + lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, + "NSDictionary synthetic children", "__CFDictionary", + ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSErrorSyntheticFrontEndCreator, + "NSError synthetic children", "NSError", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, + "NSException synthetic children", "NSException", + ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic( + objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "NSSet synthetic children", "NSSet", ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__NSSetI synthetic children", "__NSSetI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__NSSetM synthetic children", "__NSSetM", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__NSCFSet synthetic children", "__NSCFSet", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "CFSetRef synthetic children", "CFSetRef", + ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "NSMutableSet synthetic children", "NSMutableSet", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "NSOrderedSet synthetic children", "NSOrderedSet", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__NSOrderedSetI synthetic children", "__NSOrderedSetI", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__NSOrderedSetM synthetic children", "__NSOrderedSetM", + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSSetSyntheticFrontEndCreator, + "__CFSet synthetic children", "__CFSet", + ScriptedSyntheticChildren::Flags()); + + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, + "NSIndexPath synthetic children", "NSIndexPath", + ScriptedSyntheticChildren::Flags()); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBagSummaryProvider, + "CFBag summary provider", "CFBagRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBagSummaryProvider, + "CFBag summary provider", "__CFBag", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBagSummaryProvider, + "CFBag summary provider", "const struct __CFBag", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBagSummaryProvider, + "CFBag summary provider", "CFMutableBagRef", appkit_flags); + + AddCXXSummary( + objc_category_sp, lldb_private::formatters::CFBinaryHeapSummaryProvider, + "CFBinaryHeap summary provider", "CFBinaryHeapRef", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::CFBinaryHeapSummaryProvider, + "CFBinaryHeap summary provider", "__CFBinaryHeap", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSString", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "CFStringRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "__CFString", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "CFMutableStringRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSMutableString", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "__NSCFConstantString", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "__NSCFString", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSCFConstantString", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSCFString", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSPathStore2", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, + "NSString summary provider", "NSTaggedPointerString", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSAttributedStringSummaryProvider, + "NSAttributedString summary provider", "NSAttributedString", + appkit_flags); + AddCXXSummary( + objc_category_sp, + lldb_private::formatters::NSMutableAttributedStringSummaryProvider, + "NSMutableAttributedString summary provider", "NSMutableAttributedString", + appkit_flags); + AddCXXSummary( + objc_category_sp, + lldb_private::formatters::NSMutableAttributedStringSummaryProvider, + "NSMutableAttributedString summary provider", + "NSConcreteMutableAttributedString", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSBundleSummaryProvider, + "NSBundle summary provider", "NSBundle", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "NSData", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "_NSInlineData", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "NSConcreteData", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "NSConcreteMutableData", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "NSMutableData", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<false>, + "NSData summary provider", "__NSCFData", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<true>, + "NSData summary provider", "CFDataRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDataSummaryProvider<true>, + "NSData summary provider", "CFMutableDataRef", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSMachPortSummaryProvider, + "NSMachPort summary provider", "NSMachPort", appkit_flags); + + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, + "NSNotification summary provider", "NSNotification", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNotificationSummaryProvider, + "NSNotification summary provider", "NSConcreteNotification", + appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSNumber", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSConstantIntegerNumber", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSConstantDoubleNumber", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSConstantFloatNumber", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "CFNumberRef summary provider", "CFNumberRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "__NSCFBoolean", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "__NSCFNumber", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSCFBoolean", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSNumberSummaryProvider, + "NSNumber summary provider", "NSCFNumber", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, + "NSDecimalNumber summary provider", "NSDecimalNumber", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSURLSummaryProvider, + "NSURL summary provider", "NSURL", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSURLSummaryProvider, + "NSURL summary provider", "CFURLRef", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDateSummaryProvider, + "NSDate summary provider", "NSDate", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDateSummaryProvider, + "NSDate summary provider", "__NSDate", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDateSummaryProvider, + "NSDate summary provider", "__NSTaggedDate", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSDateSummaryProvider, + "NSDate summary provider", "NSCalendarDate", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSTimeZoneSummaryProvider, + "NSTimeZone summary provider", "NSTimeZone", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSTimeZoneSummaryProvider, + "NSTimeZone summary provider", "CFTimeZoneRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSTimeZoneSummaryProvider, + "NSTimeZone summary provider", "__NSTimeZone", appkit_flags); + + // CFAbsoluteTime is actually a double rather than a pointer to an object we + // do not care about the numeric value, since it is probably meaningless to + // users + appkit_flags.SetDontShowValue(true); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, + "CFAbsoluteTime summary provider", "CFAbsoluteTime", appkit_flags); + appkit_flags.SetDontShowValue(false); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::NSIndexSetSummaryProvider, + "NSIndexSet summary provider", "NSIndexSet", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, + "NSIndexSet summary provider", "NSMutableIndexSet", appkit_flags); + + AddStringSummary(objc_category_sp, + "@\"${var.month%d}/${var.day%d}/${var.year%d} " + "${var.hour%d}:${var.minute%d}:${var.second}\"", + "CFGregorianDate", appkit_flags); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBitVectorSummaryProvider, + "CFBitVector summary provider", "CFBitVectorRef", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, + "CFBitVector summary provider", "CFMutableBitVectorRef", appkit_flags); + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CFBitVectorSummaryProvider, + "CFBitVector summary provider", "__CFBitVector", appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, + "CFBitVector summary provider", "__CFMutableBitVector", appkit_flags); +} + +static void LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) { + if (!objc_category_sp) + return; + + TypeSummaryImpl::Flags cm_flags; + cm_flags.SetCascades(true) + .SetDontShowChildren(false) + .SetDontShowValue(false) + .SetHideItemNames(false) + .SetShowMembersOneLiner(false) + .SetSkipPointers(false) + .SetSkipReferences(false); + + AddCXXSummary(objc_category_sp, + lldb_private::formatters::CMTimeSummaryProvider, + "CMTime summary provider", "CMTime", cm_flags); +} + +lldb::TypeCategoryImplSP ObjCLanguage::GetFormatters() { + static llvm::once_flag g_initialize; + static TypeCategoryImplSP g_category; + + llvm::call_once(g_initialize, [this]() -> void { + DataVisualization::Categories::GetCategory(ConstString(GetPluginName()), + g_category); + if (g_category) { + LoadCoreMediaFormatters(g_category); + LoadObjCFormatters(g_category); + } + }); + return g_category; +} + +std::vector<FormattersMatchCandidate> +ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj, + lldb::DynamicValueType use_dynamic) { + std::vector<FormattersMatchCandidate> result; + + if (use_dynamic == lldb::eNoDynamicValues) + return result; + + CompilerType compiler_type(valobj.GetCompilerType()); + + const bool check_cpp = false; + const bool check_objc = true; + bool canBeObjCDynamic = + compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc); + + if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) { + do { + lldb::ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + break; + ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); + if (runtime == nullptr) + break; + ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp( + runtime->GetClassDescriptor(valobj)); + if (!objc_class_sp) + break; + if (ConstString name = objc_class_sp->GetClassName()) + result.push_back( + {name, valobj.GetTargetSP()->GetDebugger().GetScriptInterpreter(), + TypeImpl(objc_class_sp->GetType()), + FormattersMatchCandidate::Flags{}}); + } while (false); + } + + return result; +} + +std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() { + class ObjCScavengerResult : public Language::TypeScavenger::Result { + public: + ObjCScavengerResult(CompilerType type) + : Language::TypeScavenger::Result(), m_compiler_type(type) {} + + bool IsValid() override { return m_compiler_type.IsValid(); } + + bool DumpToStream(Stream &stream, bool print_help_if_available) override { + if (IsValid()) { + m_compiler_type.DumpTypeDescription(&stream); + stream.EOL(); + return true; + } + return false; + } + + private: + CompilerType m_compiler_type; + }; + + class ObjCRuntimeScavenger : public Language::TypeScavenger { + protected: + bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, + ResultSet &results) override { + bool result = false; + + if (auto *process = exe_scope->CalculateProcess().get()) { + if (auto *objc_runtime = ObjCLanguageRuntime::Get(*process)) { + if (auto *decl_vendor = objc_runtime->GetDeclVendor()) { + ConstString name(key); + for (const CompilerType &type : + decl_vendor->FindTypes(name, /*max_matches*/ UINT32_MAX)) { + result = true; + std::unique_ptr<Language::TypeScavenger::Result> result( + new ObjCScavengerResult(type)); + results.insert(std::move(result)); + } + } + } + } + + return result; + } + + friend class lldb_private::ObjCLanguage; + }; + + class ObjCModulesScavenger : public Language::TypeScavenger { + protected: + bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, + ResultSet &results) override { + bool result = false; + + if (auto *target = exe_scope->CalculateTarget().get()) { + auto *persistent_vars = llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)); + if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor = + persistent_vars->GetClangModulesDeclVendor()) { + ConstString key_cs(key); + auto types = clang_modules_decl_vendor->FindTypes( + key_cs, /*max_matches*/ UINT32_MAX); + if (!types.empty()) { + result = true; + std::unique_ptr<Language::TypeScavenger::Result> result( + new ObjCScavengerResult(types.front())); + results.insert(std::move(result)); + } + } + } + + return result; + } + + friend class lldb_private::ObjCLanguage; + }; + + class ObjCDebugInfoScavenger : public Language::ImageListTypeScavenger { + public: + CompilerType AdjustForInclusion(CompilerType &candidate) override { + LanguageType lang_type(candidate.GetMinimumLanguage()); + if (!Language::LanguageIsObjC(lang_type)) + return CompilerType(); + if (candidate.IsTypedefType()) + return candidate.GetTypedefedType(); + return candidate; + } + }; + + return std::unique_ptr<TypeScavenger>( + new Language::EitherTypeScavenger<ObjCModulesScavenger, + ObjCRuntimeScavenger, + ObjCDebugInfoScavenger>()); +} + +std::pair<llvm::StringRef, llvm::StringRef> +ObjCLanguage::GetFormatterPrefixSuffix(llvm::StringRef type_hint) { + static constexpr llvm::StringRef empty; + static const llvm::StringMap< + std::pair<const llvm::StringRef, const llvm::StringRef>> + g_affix_map = { + {"CFBag", {"@", empty}}, + {"CFBinaryHeap", {"@", empty}}, + {"NSString", {"@", empty}}, + {"NSString*", {"@", empty}}, + {"NSNumber:char", {"(char)", empty}}, + {"NSNumber:short", {"(short)", empty}}, + {"NSNumber:int", {"(int)", empty}}, + {"NSNumber:long", {"(long)", empty}}, + {"NSNumber:int128_t", {"(int128_t)", empty}}, + {"NSNumber:float", {"(float)", empty}}, + {"NSNumber:double", {"(double)", empty}}, + {"NSData", {"@\"", "\""}}, + {"NSArray", {"@\"", "\""}}, + }; + return g_affix_map.lookup(type_hint); +} + +bool ObjCLanguage::IsNilReference(ValueObject &valobj) { + const uint32_t mask = eTypeIsObjC | eTypeIsPointer; + bool isObjCpointer = + (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask); + if (!isObjCpointer) + return false; + bool canReadValue = true; + bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0; + return canReadValue && isZero; +} + +bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const { + const auto suffixes = {".h", ".m", ".M"}; + for (auto suffix : suffixes) { + if (file_path.ends_with_insensitive(suffix)) + return true; + } + return false; +} |