Files
clang-p2996/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
Jonas Devlieghere b852fb1ec5 [lldb] Move ValueObject into its own library (NFC) (#113393)
ValueObject is part of lldbCore for historical reasons, but conceptually
it deserves to be its own library. This does introduce a (link-time) circular
dependency between lldbCore and lldbValueObject, which is unfortunate
but probably unavoidable because so many things in LLDB rely on
ValueObject. We already have cycles and these libraries are never built
as dylibs so while this doesn't improve the situation, it also doesn't
make things worse.

The header includes were updated with the following command:

```
find . -type f -exec sed -i.bak "s%include \"lldb/Core/ValueObject%include \"lldb/ValueObject/ValueObject%" '{}' \;
```
2024-10-24 20:20:48 -07:00

1043 lines
44 KiB
C++

//===-- 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/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 "lldb/ValueObject/ValueObject.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;
}