1061da546Spatrick //===-- ObjCLanguageRuntime.h -----------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 11061da546Spatrick 12061da546Spatrick #include <functional> 13061da546Spatrick #include <map> 14061da546Spatrick #include <memory> 15*f6aab3d8Srobert #include <optional> 16061da546Spatrick #include <unordered_set> 17061da546Spatrick 18061da546Spatrick #include "llvm/Support/Casting.h" 19061da546Spatrick 20061da546Spatrick #include "lldb/Breakpoint/BreakpointPrecondition.h" 21061da546Spatrick #include "lldb/Core/PluginInterface.h" 22061da546Spatrick #include "lldb/Core/ThreadSafeDenseMap.h" 23061da546Spatrick #include "lldb/Symbol/CompilerType.h" 24061da546Spatrick #include "lldb/Symbol/Type.h" 25061da546Spatrick #include "lldb/Target/LanguageRuntime.h" 26*f6aab3d8Srobert #include "lldb/Utility/ConstString.h" 27061da546Spatrick #include "lldb/lldb-private.h" 28061da546Spatrick 29061da546Spatrick class CommandObjectObjC_ClassTable_Dump; 30061da546Spatrick 31061da546Spatrick namespace lldb_private { 32061da546Spatrick 33dda28197Spatrick class TypeSystemClang; 34061da546Spatrick class UtilityFunction; 35061da546Spatrick 36061da546Spatrick class ObjCLanguageRuntime : public LanguageRuntime { 37061da546Spatrick public: 38061da546Spatrick enum class ObjCRuntimeVersions { 39061da546Spatrick eObjC_VersionUnknown = 0, 40061da546Spatrick eAppleObjC_V1 = 1, 41061da546Spatrick eAppleObjC_V2 = 2 42061da546Spatrick }; 43061da546Spatrick 44061da546Spatrick typedef lldb::addr_t ObjCISA; 45061da546Spatrick 46061da546Spatrick class ClassDescriptor; 47061da546Spatrick typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP; 48061da546Spatrick 49061da546Spatrick // the information that we want to support retrieving from an ObjC class this 50061da546Spatrick // needs to be pure virtual since there are at least 2 different 51061da546Spatrick // implementations of the runtime, and more might come 52061da546Spatrick class ClassDescriptor { 53061da546Spatrick public: ClassDescriptor()54be691f3bSpatrick ClassDescriptor() : m_type_wp() {} 55061da546Spatrick 56061da546Spatrick virtual ~ClassDescriptor() = default; 57061da546Spatrick 58061da546Spatrick virtual ConstString GetClassName() = 0; 59061da546Spatrick 60061da546Spatrick virtual ClassDescriptorSP GetSuperclass() = 0; 61061da546Spatrick 62061da546Spatrick virtual ClassDescriptorSP GetMetaclass() const = 0; 63061da546Spatrick 64061da546Spatrick // virtual if any implementation has some other version-specific rules but 65061da546Spatrick // for the known v1/v2 this is all that needs to be done IsKVO()66061da546Spatrick virtual bool IsKVO() { 67061da546Spatrick if (m_is_kvo == eLazyBoolCalculate) { 68061da546Spatrick const char *class_name = GetClassName().AsCString(); 69061da546Spatrick if (class_name && *class_name) 70061da546Spatrick m_is_kvo = 71061da546Spatrick (LazyBool)(strstr(class_name, "NSKVONotifying_") == class_name); 72061da546Spatrick } 73061da546Spatrick return (m_is_kvo == eLazyBoolYes); 74061da546Spatrick } 75061da546Spatrick 76061da546Spatrick // virtual if any implementation has some other version-specific rules but 77061da546Spatrick // for the known v1/v2 this is all that needs to be done IsCFType()78061da546Spatrick virtual bool IsCFType() { 79061da546Spatrick if (m_is_cf == eLazyBoolCalculate) { 80061da546Spatrick const char *class_name = GetClassName().AsCString(); 81061da546Spatrick if (class_name && *class_name) 82061da546Spatrick m_is_cf = (LazyBool)(strcmp(class_name, "__NSCFType") == 0 || 83061da546Spatrick strcmp(class_name, "NSCFType") == 0); 84061da546Spatrick } 85061da546Spatrick return (m_is_cf == eLazyBoolYes); 86061da546Spatrick } 87061da546Spatrick 88061da546Spatrick virtual bool IsValid() = 0; 89061da546Spatrick 90be691f3bSpatrick /// There are two routines in the ObjC runtime that tagged pointer clients 91be691f3bSpatrick /// can call to get the value from their tagged pointer, one that retrieves 92be691f3bSpatrick /// it as an unsigned value and one a signed value. These two 93be691f3bSpatrick /// GetTaggedPointerInfo methods mirror those two ObjC runtime calls. 94be691f3bSpatrick /// @{ 95061da546Spatrick virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr, 96061da546Spatrick uint64_t *value_bits = nullptr, 97061da546Spatrick uint64_t *payload = nullptr) = 0; 98061da546Spatrick 99be691f3bSpatrick virtual bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, 100be691f3bSpatrick int64_t *value_bits = nullptr, 101be691f3bSpatrick uint64_t *payload = nullptr) = 0; 102be691f3bSpatrick /// @} 103be691f3bSpatrick 104061da546Spatrick virtual uint64_t GetInstanceSize() = 0; 105061da546Spatrick 106061da546Spatrick // use to implement version-specific additional constraints on pointers CheckPointer(lldb::addr_t value,uint32_t ptr_size)107061da546Spatrick virtual bool CheckPointer(lldb::addr_t value, uint32_t ptr_size) const { 108061da546Spatrick return true; 109061da546Spatrick } 110061da546Spatrick 111061da546Spatrick virtual ObjCISA GetISA() = 0; 112061da546Spatrick 113061da546Spatrick // This should return true iff the interface could be completed 114061da546Spatrick virtual bool Describe(std::function<void (ObjCISA)> const & superclass_func,std::function<bool (const char *,const char *)> const & instance_method_func,std::function<bool (const char *,const char *)> const & class_method_func,std::function<bool (const char *,const char *,lldb::addr_t,uint64_t)> const & ivar_func)115061da546Spatrick Describe(std::function<void(ObjCISA)> const &superclass_func, 116061da546Spatrick std::function<bool(const char *, const char *)> const 117061da546Spatrick &instance_method_func, 118061da546Spatrick std::function<bool(const char *, const char *)> const 119061da546Spatrick &class_method_func, 120061da546Spatrick std::function<bool(const char *, const char *, lldb::addr_t, 121061da546Spatrick uint64_t)> const &ivar_func) const { 122061da546Spatrick return false; 123061da546Spatrick } 124061da546Spatrick GetType()125061da546Spatrick lldb::TypeSP GetType() { return m_type_wp.lock(); } 126061da546Spatrick SetType(const lldb::TypeSP & type_sp)127061da546Spatrick void SetType(const lldb::TypeSP &type_sp) { m_type_wp = type_sp; } 128061da546Spatrick 129061da546Spatrick struct iVarDescriptor { 130061da546Spatrick ConstString m_name; 131061da546Spatrick CompilerType m_type; 132061da546Spatrick uint64_t m_size; 133061da546Spatrick int32_t m_offset; 134061da546Spatrick }; 135061da546Spatrick GetNumIVars()136061da546Spatrick virtual size_t GetNumIVars() { return 0; } 137061da546Spatrick GetIVarAtIndex(size_t idx)138061da546Spatrick virtual iVarDescriptor GetIVarAtIndex(size_t idx) { 139061da546Spatrick return iVarDescriptor(); 140061da546Spatrick } 141061da546Spatrick 142061da546Spatrick protected: 143061da546Spatrick bool IsPointerValid(lldb::addr_t value, uint32_t ptr_size, 144061da546Spatrick bool allow_NULLs = false, bool allow_tagged = false, 145061da546Spatrick bool check_version_specific = false) const; 146061da546Spatrick 147061da546Spatrick private: 148be691f3bSpatrick LazyBool m_is_kvo = eLazyBoolCalculate; 149be691f3bSpatrick LazyBool m_is_cf = eLazyBoolCalculate; 150061da546Spatrick lldb::TypeWP m_type_wp; 151061da546Spatrick }; 152061da546Spatrick 153061da546Spatrick class EncodingToType { 154061da546Spatrick public: 155061da546Spatrick virtual ~EncodingToType(); 156061da546Spatrick 157dda28197Spatrick virtual CompilerType RealizeType(TypeSystemClang &ast_ctx, const char *name, 158061da546Spatrick bool for_expression) = 0; 159061da546Spatrick virtual CompilerType RealizeType(const char *name, bool for_expression); 160061da546Spatrick 161061da546Spatrick protected: 162*f6aab3d8Srobert std::shared_ptr<TypeSystemClang> m_scratch_ast_ctx_sp; 163061da546Spatrick }; 164061da546Spatrick 165061da546Spatrick class ObjCExceptionPrecondition : public BreakpointPrecondition { 166061da546Spatrick public: 167061da546Spatrick ObjCExceptionPrecondition(); 168061da546Spatrick 169061da546Spatrick ~ObjCExceptionPrecondition() override = default; 170061da546Spatrick 171061da546Spatrick bool EvaluatePrecondition(StoppointCallbackContext &context) override; 172061da546Spatrick void GetDescription(Stream &stream, lldb::DescriptionLevel level) override; 173061da546Spatrick Status ConfigurePrecondition(Args &args) override; 174061da546Spatrick 175061da546Spatrick protected: 176061da546Spatrick void AddClassName(const char *class_name); 177061da546Spatrick 178061da546Spatrick private: 179061da546Spatrick std::unordered_set<std::string> m_class_names; 180061da546Spatrick }; 181061da546Spatrick 182061da546Spatrick static lldb::BreakpointPreconditionSP 183061da546Spatrick GetBreakpointExceptionPrecondition(lldb::LanguageType language, 184061da546Spatrick bool throw_bp); 185061da546Spatrick 186061da546Spatrick class TaggedPointerVendor { 187061da546Spatrick public: 188061da546Spatrick virtual ~TaggedPointerVendor() = default; 189061da546Spatrick 190061da546Spatrick virtual bool IsPossibleTaggedPointer(lldb::addr_t ptr) = 0; 191061da546Spatrick 192061da546Spatrick virtual ObjCLanguageRuntime::ClassDescriptorSP 193061da546Spatrick GetClassDescriptor(lldb::addr_t ptr) = 0; 194061da546Spatrick 195061da546Spatrick protected: 196061da546Spatrick TaggedPointerVendor() = default; 197061da546Spatrick 198061da546Spatrick private: 199dda28197Spatrick TaggedPointerVendor(const TaggedPointerVendor &) = delete; 200dda28197Spatrick const TaggedPointerVendor &operator=(const TaggedPointerVendor &) = delete; 201061da546Spatrick }; 202061da546Spatrick 203061da546Spatrick ~ObjCLanguageRuntime() override; 204061da546Spatrick 205061da546Spatrick static char ID; 206061da546Spatrick isA(const void * ClassID)207061da546Spatrick bool isA(const void *ClassID) const override { 208061da546Spatrick return ClassID == &ID || LanguageRuntime::isA(ClassID); 209061da546Spatrick } 210061da546Spatrick classof(const LanguageRuntime * runtime)211061da546Spatrick static bool classof(const LanguageRuntime *runtime) { 212061da546Spatrick return runtime->isA(&ID); 213061da546Spatrick } 214061da546Spatrick Get(Process & process)215061da546Spatrick static ObjCLanguageRuntime *Get(Process &process) { 216061da546Spatrick return llvm::cast_or_null<ObjCLanguageRuntime>( 217061da546Spatrick process.GetLanguageRuntime(lldb::eLanguageTypeObjC)); 218061da546Spatrick } 219061da546Spatrick GetTaggedPointerVendor()220061da546Spatrick virtual TaggedPointerVendor *GetTaggedPointerVendor() { return nullptr; } 221061da546Spatrick 222061da546Spatrick typedef std::shared_ptr<EncodingToType> EncodingToTypeSP; 223061da546Spatrick 224061da546Spatrick virtual EncodingToTypeSP GetEncodingToType(); 225061da546Spatrick 226061da546Spatrick virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value); 227061da546Spatrick 228061da546Spatrick ClassDescriptorSP GetNonKVOClassDescriptor(ValueObject &in_value); 229061da546Spatrick 230061da546Spatrick virtual ClassDescriptorSP 231061da546Spatrick GetClassDescriptorFromClassName(ConstString class_name); 232061da546Spatrick 233061da546Spatrick virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa); 234061da546Spatrick 235061da546Spatrick ClassDescriptorSP GetNonKVOClassDescriptor(ObjCISA isa); 236061da546Spatrick GetLanguageType()237061da546Spatrick lldb::LanguageType GetLanguageType() const override { 238061da546Spatrick return lldb::eLanguageTypeObjC; 239061da546Spatrick } 240061da546Spatrick 241061da546Spatrick virtual bool IsModuleObjCLibrary(const lldb::ModuleSP &module_sp) = 0; 242061da546Spatrick 243061da546Spatrick virtual bool ReadObjCLibrary(const lldb::ModuleSP &module_sp) = 0; 244061da546Spatrick 245061da546Spatrick virtual bool HasReadObjCLibrary() = 0; 246061da546Spatrick 247*f6aab3d8Srobert // These two methods actually use different caches. The only time we'll 248*f6aab3d8Srobert // cache a sel_str is if we found a "selector specific stub" for the selector 249*f6aab3d8Srobert // and conversely we only add to the SEL cache if we saw a regular dispatch. 250061da546Spatrick lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, lldb::addr_t sel); 251*f6aab3d8Srobert lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, 252*f6aab3d8Srobert llvm::StringRef sel_str); 253061da546Spatrick 254061da546Spatrick void AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t sel, 255061da546Spatrick lldb::addr_t impl_addr); 256061da546Spatrick 257*f6aab3d8Srobert void AddToMethodCache(lldb::addr_t class_addr, llvm::StringRef sel_str, 258*f6aab3d8Srobert lldb::addr_t impl_addr); 259*f6aab3d8Srobert 260061da546Spatrick TypeAndOrName LookupInClassNameCache(lldb::addr_t class_addr); 261061da546Spatrick 262061da546Spatrick void AddToClassNameCache(lldb::addr_t class_addr, const char *name, 263061da546Spatrick lldb::TypeSP type_sp); 264061da546Spatrick 265061da546Spatrick void AddToClassNameCache(lldb::addr_t class_addr, 266061da546Spatrick const TypeAndOrName &class_or_type_name); 267061da546Spatrick 268061da546Spatrick lldb::TypeSP LookupInCompleteClassCache(ConstString &name); 269061da546Spatrick 270*f6aab3d8Srobert std::optional<CompilerType> GetRuntimeType(CompilerType base_type) override; 271061da546Spatrick 272be691f3bSpatrick virtual llvm::Expected<std::unique_ptr<UtilityFunction>> 273be691f3bSpatrick CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) = 0; 274061da546Spatrick GetRuntimeVersion()275061da546Spatrick virtual ObjCRuntimeVersions GetRuntimeVersion() const { 276061da546Spatrick return ObjCRuntimeVersions::eObjC_VersionUnknown; 277061da546Spatrick } 278061da546Spatrick IsValidISA(ObjCISA isa)279061da546Spatrick bool IsValidISA(ObjCISA isa) { 280061da546Spatrick UpdateISAToDescriptorMap(); 281061da546Spatrick return m_isa_to_descriptor.count(isa) > 0; 282061da546Spatrick } 283061da546Spatrick 284061da546Spatrick virtual void UpdateISAToDescriptorMapIfNeeded() = 0; 285061da546Spatrick UpdateISAToDescriptorMap()286061da546Spatrick void UpdateISAToDescriptorMap() { 287061da546Spatrick if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id) { 288061da546Spatrick UpdateISAToDescriptorMapIfNeeded(); 289061da546Spatrick } 290061da546Spatrick } 291061da546Spatrick 292061da546Spatrick virtual ObjCISA GetISA(ConstString name); 293061da546Spatrick 294061da546Spatrick virtual ObjCISA GetParentClass(ObjCISA isa); 295061da546Spatrick 296061da546Spatrick // Finds the byte offset of the child_type ivar in parent_type. If it can't 297061da546Spatrick // find the offset, returns LLDB_INVALID_IVAR_OFFSET. 298061da546Spatrick 299061da546Spatrick virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, 300061da546Spatrick const char *ivar_name); 301061da546Spatrick HasNewLiteralsAndIndexing()302061da546Spatrick bool HasNewLiteralsAndIndexing() { 303061da546Spatrick if (m_has_new_literals_and_indexing == eLazyBoolCalculate) { 304061da546Spatrick if (CalculateHasNewLiteralsAndIndexing()) 305061da546Spatrick m_has_new_literals_and_indexing = eLazyBoolYes; 306061da546Spatrick else 307061da546Spatrick m_has_new_literals_and_indexing = eLazyBoolNo; 308061da546Spatrick } 309061da546Spatrick 310061da546Spatrick return (m_has_new_literals_and_indexing == eLazyBoolYes); 311061da546Spatrick } 312061da546Spatrick SymbolsDidLoad(const ModuleList & module_list)313061da546Spatrick void SymbolsDidLoad(const ModuleList &module_list) override { 314061da546Spatrick m_negative_complete_class_cache.clear(); 315061da546Spatrick } 316061da546Spatrick 317061da546Spatrick bool GetTypeBitSize(const CompilerType &compiler_type, 318061da546Spatrick uint64_t &size) override; 319061da546Spatrick 320061da546Spatrick /// Check whether the name is "self" or "_cmd" and should show up in 321061da546Spatrick /// "frame variable". 322dda28197Spatrick bool IsAllowedRuntimeValue(ConstString name) override; 323061da546Spatrick 324061da546Spatrick protected: 325061da546Spatrick // Classes that inherit from ObjCLanguageRuntime can see and modify these 326061da546Spatrick ObjCLanguageRuntime(Process *process); 327061da546Spatrick CalculateHasNewLiteralsAndIndexing()328061da546Spatrick virtual bool CalculateHasNewLiteralsAndIndexing() { return false; } 329061da546Spatrick ISAIsCached(ObjCISA isa)330061da546Spatrick bool ISAIsCached(ObjCISA isa) const { 331061da546Spatrick return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end(); 332061da546Spatrick } 333061da546Spatrick AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp)334061da546Spatrick bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp) { 335061da546Spatrick if (isa != 0) { 336061da546Spatrick m_isa_to_descriptor[isa] = descriptor_sp; 337061da546Spatrick return true; 338061da546Spatrick } 339061da546Spatrick return false; 340061da546Spatrick } 341061da546Spatrick 342061da546Spatrick bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, 343061da546Spatrick const char *class_name); 344061da546Spatrick AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp,uint32_t class_name_hash)345061da546Spatrick bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, 346061da546Spatrick uint32_t class_name_hash) { 347061da546Spatrick if (isa != 0) { 348061da546Spatrick m_isa_to_descriptor[isa] = descriptor_sp; 349061da546Spatrick m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa)); 350061da546Spatrick return true; 351061da546Spatrick } 352061da546Spatrick return false; 353061da546Spatrick } 354061da546Spatrick 355061da546Spatrick private: 356*f6aab3d8Srobert // We keep two maps of <Class,Selector>->Implementation so we don't have 357*f6aab3d8Srobert // to call the resolver function over and over. 358*f6aab3d8Srobert // The first comes from regular obj_msgSend type dispatch, and maps the 359*f6aab3d8Srobert // class + uniqued SEL value to an implementation. 360*f6aab3d8Srobert // The second comes from the "selector-specific stubs", which are always 361*f6aab3d8Srobert // of the form _objc_msgSend$SelectorName, so we don't know the uniqued 362*f6aab3d8Srobert // selector, only the string name. 363061da546Spatrick 364061da546Spatrick // FIXME: We need to watch for the loading of Protocols, and flush the cache 365061da546Spatrick // for any 366061da546Spatrick // class that we see so changed. 367061da546Spatrick 368061da546Spatrick struct ClassAndSel { 369*f6aab3d8Srobert ClassAndSel() = default; 370061da546Spatrick ClassAndSelClassAndSel371*f6aab3d8Srobert ClassAndSel(lldb::addr_t in_class_addr, lldb::addr_t in_sel_addr) 372061da546Spatrick : class_addr(in_class_addr), sel_addr(in_sel_addr) {} 373061da546Spatrick 374061da546Spatrick bool operator==(const ClassAndSel &rhs) { 375061da546Spatrick if (class_addr == rhs.class_addr && sel_addr == rhs.sel_addr) 376061da546Spatrick return true; 377061da546Spatrick else 378061da546Spatrick return false; 379061da546Spatrick } 380061da546Spatrick 381061da546Spatrick bool operator<(const ClassAndSel &rhs) const { 382061da546Spatrick if (class_addr < rhs.class_addr) 383061da546Spatrick return true; 384061da546Spatrick else if (class_addr > rhs.class_addr) 385061da546Spatrick return false; 386061da546Spatrick else { 387061da546Spatrick if (sel_addr < rhs.sel_addr) 388061da546Spatrick return true; 389061da546Spatrick else 390061da546Spatrick return false; 391061da546Spatrick } 392061da546Spatrick } 393061da546Spatrick 394*f6aab3d8Srobert lldb::addr_t class_addr = LLDB_INVALID_ADDRESS; 395*f6aab3d8Srobert lldb::addr_t sel_addr = LLDB_INVALID_ADDRESS; 396*f6aab3d8Srobert }; 397*f6aab3d8Srobert 398*f6aab3d8Srobert struct ClassAndSelStr { 399*f6aab3d8Srobert ClassAndSelStr() = default; 400*f6aab3d8Srobert ClassAndSelStrClassAndSelStr401*f6aab3d8Srobert ClassAndSelStr(lldb::addr_t in_class_addr, llvm::StringRef in_sel_name) 402*f6aab3d8Srobert : class_addr(in_class_addr), sel_name(in_sel_name) {} 403*f6aab3d8Srobert 404*f6aab3d8Srobert bool operator==(const ClassAndSelStr &rhs) { 405*f6aab3d8Srobert return class_addr == rhs.class_addr && sel_name == rhs.sel_name; 406*f6aab3d8Srobert } 407*f6aab3d8Srobert 408*f6aab3d8Srobert bool operator<(const ClassAndSelStr &rhs) const { 409*f6aab3d8Srobert if (class_addr < rhs.class_addr) 410*f6aab3d8Srobert return true; 411*f6aab3d8Srobert else if (class_addr > rhs.class_addr) 412*f6aab3d8Srobert return false; 413*f6aab3d8Srobert else 414*f6aab3d8Srobert return ConstString::Compare(sel_name, rhs.sel_name); 415*f6aab3d8Srobert } 416*f6aab3d8Srobert 417*f6aab3d8Srobert lldb::addr_t class_addr = LLDB_INVALID_ADDRESS; 418*f6aab3d8Srobert ConstString sel_name; 419061da546Spatrick }; 420061da546Spatrick 421061da546Spatrick typedef std::map<ClassAndSel, lldb::addr_t> MsgImplMap; 422*f6aab3d8Srobert typedef std::map<ClassAndSelStr, lldb::addr_t> MsgImplStrMap; 423061da546Spatrick typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; 424061da546Spatrick typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; 425061da546Spatrick typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; 426061da546Spatrick typedef HashToISAMap::iterator HashToISAIterator; 427061da546Spatrick typedef ThreadSafeDenseMap<void *, uint64_t> TypeSizeCache; 428061da546Spatrick 429061da546Spatrick MsgImplMap m_impl_cache; 430*f6aab3d8Srobert MsgImplStrMap m_impl_str_cache; 431061da546Spatrick LazyBool m_has_new_literals_and_indexing; 432061da546Spatrick ISAToDescriptorMap m_isa_to_descriptor; 433061da546Spatrick HashToISAMap m_hash_to_isa_map; 434061da546Spatrick TypeSizeCache m_type_size_cache; 435061da546Spatrick 436061da546Spatrick protected: 437061da546Spatrick uint32_t m_isa_to_descriptor_stop_id; 438061da546Spatrick 439061da546Spatrick typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; 440061da546Spatrick CompleteClassMap m_complete_class_cache; 441061da546Spatrick 442061da546Spatrick struct ConstStringSetHelpers { operatorConstStringSetHelpers443061da546Spatrick size_t operator()(ConstString arg) const // for hashing 444061da546Spatrick { 445061da546Spatrick return (size_t)arg.GetCString(); 446061da546Spatrick } operatorConstStringSetHelpers447061da546Spatrick bool operator()(ConstString arg1, 448061da546Spatrick ConstString arg2) const // for equality 449061da546Spatrick { 450061da546Spatrick return arg1.operator==(arg2); 451061da546Spatrick } 452061da546Spatrick }; 453061da546Spatrick typedef std::unordered_set<ConstString, ConstStringSetHelpers, 454061da546Spatrick ConstStringSetHelpers> 455061da546Spatrick CompleteClassSet; 456061da546Spatrick CompleteClassSet m_negative_complete_class_cache; 457061da546Spatrick 458061da546Spatrick ISAToDescriptorIterator GetDescriptorIterator(ConstString name); 459061da546Spatrick 460061da546Spatrick friend class ::CommandObjectObjC_ClassTable_Dump; 461061da546Spatrick 462061da546Spatrick std::pair<ISAToDescriptorIterator, ISAToDescriptorIterator> 463061da546Spatrick GetDescriptorIteratorPair(bool update_if_needed = true); 464061da546Spatrick 465061da546Spatrick void ReadObjCLibraryIfNeeded(const ModuleList &module_list); 466061da546Spatrick 467dda28197Spatrick ObjCLanguageRuntime(const ObjCLanguageRuntime &) = delete; 468dda28197Spatrick const ObjCLanguageRuntime &operator=(const ObjCLanguageRuntime &) = delete; 469061da546Spatrick }; 470061da546Spatrick 471061da546Spatrick } // namespace lldb_private 472061da546Spatrick 473dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 474