1b5701710SAlex Langford //===-- ObjCLanguageRuntime.h -----------------------------------*- C++ -*-===// 2b5701710SAlex Langford // 3b5701710SAlex Langford // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b5701710SAlex Langford // See https://llvm.org/LICENSE.txt for license information. 5b5701710SAlex Langford // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b5701710SAlex Langford // 7b5701710SAlex Langford //===----------------------------------------------------------------------===// 8b5701710SAlex Langford 9cdc514e4SJonas Devlieghere #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 10cdc514e4SJonas Devlieghere #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 11b5701710SAlex Langford 12b5701710SAlex Langford #include <functional> 13b5701710SAlex Langford #include <map> 14b5701710SAlex Langford #include <memory> 15f190ce62SKazu Hirata #include <optional> 16b5701710SAlex Langford #include <unordered_set> 17b5701710SAlex Langford 18b5701710SAlex Langford #include "llvm/Support/Casting.h" 19b5701710SAlex Langford 20b5701710SAlex Langford #include "lldb/Breakpoint/BreakpointPrecondition.h" 21b5701710SAlex Langford #include "lldb/Core/PluginInterface.h" 22b5701710SAlex Langford #include "lldb/Symbol/CompilerType.h" 23b5701710SAlex Langford #include "lldb/Symbol/Type.h" 24b5701710SAlex Langford #include "lldb/Target/LanguageRuntime.h" 25833882b3SJim Ingham #include "lldb/Utility/ConstString.h" 26147a6161SAlex Langford #include "lldb/Utility/ThreadSafeDenseMap.h" 27e19339f5SDave Lee #include "lldb/lldb-enumerations.h" 28b5701710SAlex Langford #include "lldb/lldb-private.h" 29b5701710SAlex Langford 30b5701710SAlex Langford class CommandObjectObjC_ClassTable_Dump; 31b5701710SAlex Langford 32b5701710SAlex Langford namespace lldb_private { 33b5701710SAlex Langford 347c9ebdd3SAlex Langford class TypeSystemClang; 35b5701710SAlex Langford class UtilityFunction; 36b5701710SAlex Langford 37b5701710SAlex Langford class ObjCLanguageRuntime : public LanguageRuntime { 38b5701710SAlex Langford public: 39b5701710SAlex Langford enum class ObjCRuntimeVersions { 40b5701710SAlex Langford eObjC_VersionUnknown = 0, 41b5701710SAlex Langford eAppleObjC_V1 = 1, 420b626473SStefan Gränitz eAppleObjC_V2 = 2, 430b626473SStefan Gränitz eGNUstep_libobjc2 = 3, 44b5701710SAlex Langford }; 45b5701710SAlex Langford 46b5701710SAlex Langford typedef lldb::addr_t ObjCISA; 47b5701710SAlex Langford 48b5701710SAlex Langford class ClassDescriptor; 49b5701710SAlex Langford typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP; 50b5701710SAlex Langford 51b5701710SAlex Langford // the information that we want to support retrieving from an ObjC class this 52b5701710SAlex Langford // needs to be pure virtual since there are at least 2 different 53b5701710SAlex Langford // implementations of the runtime, and more might come 54b5701710SAlex Langford class ClassDescriptor { 55b5701710SAlex Langford public: ClassDescriptor()569494c510SJonas Devlieghere ClassDescriptor() : m_type_wp() {} 57b5701710SAlex Langford 58b5701710SAlex Langford virtual ~ClassDescriptor() = default; 59b5701710SAlex Langford 60b5701710SAlex Langford virtual ConstString GetClassName() = 0; 61b5701710SAlex Langford 62b5701710SAlex Langford virtual ClassDescriptorSP GetSuperclass() = 0; 63b5701710SAlex Langford 64b5701710SAlex Langford virtual ClassDescriptorSP GetMetaclass() const = 0; 65b5701710SAlex Langford 66b5701710SAlex Langford // virtual if any implementation has some other version-specific rules but 67b5701710SAlex Langford // for the known v1/v2 this is all that needs to be done IsKVO()68b5701710SAlex Langford virtual bool IsKVO() { 69b5701710SAlex Langford if (m_is_kvo == eLazyBoolCalculate) { 70b5701710SAlex Langford const char *class_name = GetClassName().AsCString(); 71b5701710SAlex Langford if (class_name && *class_name) 72b5701710SAlex Langford m_is_kvo = 73b5701710SAlex Langford (LazyBool)(strstr(class_name, "NSKVONotifying_") == class_name); 74b5701710SAlex Langford } 75b5701710SAlex Langford return (m_is_kvo == eLazyBoolYes); 76b5701710SAlex Langford } 77b5701710SAlex Langford 78b5701710SAlex Langford // virtual if any implementation has some other version-specific rules but 79b5701710SAlex Langford // for the known v1/v2 this is all that needs to be done IsCFType()80b5701710SAlex Langford virtual bool IsCFType() { 81b5701710SAlex Langford if (m_is_cf == eLazyBoolCalculate) { 82b5701710SAlex Langford const char *class_name = GetClassName().AsCString(); 83b5701710SAlex Langford if (class_name && *class_name) 84b5701710SAlex Langford m_is_cf = (LazyBool)(strcmp(class_name, "__NSCFType") == 0 || 85b5701710SAlex Langford strcmp(class_name, "NSCFType") == 0); 86b5701710SAlex Langford } 87b5701710SAlex Langford return (m_is_cf == eLazyBoolYes); 88b5701710SAlex Langford } 89b5701710SAlex Langford 90e19339f5SDave Lee /// Determine whether this class is implemented in Swift. GetImplementationLanguage()91e19339f5SDave Lee virtual lldb::LanguageType GetImplementationLanguage() const { 92e19339f5SDave Lee return lldb::eLanguageTypeObjC; 93e19339f5SDave Lee } 94e19339f5SDave Lee 95b5701710SAlex Langford virtual bool IsValid() = 0; 96b5701710SAlex Langford 97be0ced03SJim Ingham /// There are two routines in the ObjC runtime that tagged pointer clients 98be0ced03SJim Ingham /// can call to get the value from their tagged pointer, one that retrieves 99be0ced03SJim Ingham /// it as an unsigned value and one a signed value. These two 100be0ced03SJim Ingham /// GetTaggedPointerInfo methods mirror those two ObjC runtime calls. 101be0ced03SJim Ingham /// @{ 102b5701710SAlex Langford virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr, 103b5701710SAlex Langford uint64_t *value_bits = nullptr, 104b5701710SAlex Langford uint64_t *payload = nullptr) = 0; 105b5701710SAlex Langford 106be0ced03SJim Ingham virtual bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, 107be0ced03SJim Ingham int64_t *value_bits = nullptr, 108be0ced03SJim Ingham uint64_t *payload = nullptr) = 0; 109be0ced03SJim Ingham /// @} 110be0ced03SJim Ingham 111b5701710SAlex Langford virtual uint64_t GetInstanceSize() = 0; 112b5701710SAlex Langford 113b5701710SAlex Langford // use to implement version-specific additional constraints on pointers CheckPointer(lldb::addr_t value,uint32_t ptr_size)114b5701710SAlex Langford virtual bool CheckPointer(lldb::addr_t value, uint32_t ptr_size) const { 115b5701710SAlex Langford return true; 116b5701710SAlex Langford } 117b5701710SAlex Langford 118b5701710SAlex Langford virtual ObjCISA GetISA() = 0; 119b5701710SAlex Langford 120b5701710SAlex Langford // This should return true iff the interface could be completed 121b5701710SAlex Langford 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)122b5701710SAlex Langford Describe(std::function<void(ObjCISA)> const &superclass_func, 123b5701710SAlex Langford std::function<bool(const char *, const char *)> const 124b5701710SAlex Langford &instance_method_func, 125b5701710SAlex Langford std::function<bool(const char *, const char *)> const 126b5701710SAlex Langford &class_method_func, 127b5701710SAlex Langford std::function<bool(const char *, const char *, lldb::addr_t, 128b5701710SAlex Langford uint64_t)> const &ivar_func) const { 129b5701710SAlex Langford return false; 130b5701710SAlex Langford } 131b5701710SAlex Langford GetType()132b5701710SAlex Langford lldb::TypeSP GetType() { return m_type_wp.lock(); } 133b5701710SAlex Langford SetType(const lldb::TypeSP & type_sp)134b5701710SAlex Langford void SetType(const lldb::TypeSP &type_sp) { m_type_wp = type_sp; } 135b5701710SAlex Langford 136b5701710SAlex Langford struct iVarDescriptor { 137b5701710SAlex Langford ConstString m_name; 138b5701710SAlex Langford CompilerType m_type; 139b5701710SAlex Langford uint64_t m_size; 140b5701710SAlex Langford int32_t m_offset; 141b5701710SAlex Langford }; 142b5701710SAlex Langford GetNumIVars()143b5701710SAlex Langford virtual size_t GetNumIVars() { return 0; } 144b5701710SAlex Langford GetIVarAtIndex(size_t idx)145b5701710SAlex Langford virtual iVarDescriptor GetIVarAtIndex(size_t idx) { 146b5701710SAlex Langford return iVarDescriptor(); 147b5701710SAlex Langford } 148b5701710SAlex Langford 149b5701710SAlex Langford protected: 150b5701710SAlex Langford bool IsPointerValid(lldb::addr_t value, uint32_t ptr_size, 151b5701710SAlex Langford bool allow_NULLs = false, bool allow_tagged = false, 152b5701710SAlex Langford bool check_version_specific = false) const; 153b5701710SAlex Langford 154b5701710SAlex Langford private: 1559494c510SJonas Devlieghere LazyBool m_is_kvo = eLazyBoolCalculate; 1569494c510SJonas Devlieghere LazyBool m_is_cf = eLazyBoolCalculate; 157b5701710SAlex Langford lldb::TypeWP m_type_wp; 158b5701710SAlex Langford }; 159b5701710SAlex Langford 160b5701710SAlex Langford class EncodingToType { 161b5701710SAlex Langford public: 162b5701710SAlex Langford virtual ~EncodingToType(); 163b5701710SAlex Langford 1646e3b0cc2SRaphael Isemann virtual CompilerType RealizeType(TypeSystemClang &ast_ctx, const char *name, 16537339d14SRaphael Isemann bool for_expression) = 0; 166b5701710SAlex Langford virtual CompilerType RealizeType(const char *name, bool for_expression); 167b5701710SAlex Langford 168b5701710SAlex Langford protected: 1696eaedbb5SAdrian Prantl std::shared_ptr<TypeSystemClang> m_scratch_ast_ctx_sp; 170b5701710SAlex Langford }; 171b5701710SAlex Langford 172b5701710SAlex Langford class ObjCExceptionPrecondition : public BreakpointPrecondition { 173b5701710SAlex Langford public: 174b5701710SAlex Langford ObjCExceptionPrecondition(); 175b5701710SAlex Langford 176b5701710SAlex Langford ~ObjCExceptionPrecondition() override = default; 177b5701710SAlex Langford 178b5701710SAlex Langford bool EvaluatePrecondition(StoppointCallbackContext &context) override; 179b5701710SAlex Langford void GetDescription(Stream &stream, lldb::DescriptionLevel level) override; 180b5701710SAlex Langford Status ConfigurePrecondition(Args &args) override; 181b5701710SAlex Langford 182b5701710SAlex Langford protected: 183b5701710SAlex Langford void AddClassName(const char *class_name); 184b5701710SAlex Langford 185b5701710SAlex Langford private: 186b5701710SAlex Langford std::unordered_set<std::string> m_class_names; 187b5701710SAlex Langford }; 188b5701710SAlex Langford 189b5701710SAlex Langford static lldb::BreakpointPreconditionSP 190b5701710SAlex Langford GetBreakpointExceptionPrecondition(lldb::LanguageType language, 191b5701710SAlex Langford bool throw_bp); 192b5701710SAlex Langford 193b5701710SAlex Langford class TaggedPointerVendor { 194b5701710SAlex Langford public: 195b5701710SAlex Langford virtual ~TaggedPointerVendor() = default; 196b5701710SAlex Langford 197b5701710SAlex Langford virtual bool IsPossibleTaggedPointer(lldb::addr_t ptr) = 0; 198b5701710SAlex Langford 199b5701710SAlex Langford virtual ObjCLanguageRuntime::ClassDescriptorSP 200b5701710SAlex Langford GetClassDescriptor(lldb::addr_t ptr) = 0; 201b5701710SAlex Langford 202b5701710SAlex Langford protected: 203b5701710SAlex Langford TaggedPointerVendor() = default; 204b5701710SAlex Langford 205b5701710SAlex Langford private: 206eaebcbc6SKonrad Kleine TaggedPointerVendor(const TaggedPointerVendor &) = delete; 207eaebcbc6SKonrad Kleine const TaggedPointerVendor &operator=(const TaggedPointerVendor &) = delete; 208b5701710SAlex Langford }; 209b5701710SAlex Langford 210b5701710SAlex Langford ~ObjCLanguageRuntime() override; 211b5701710SAlex Langford 212b5701710SAlex Langford static char ID; 213b5701710SAlex Langford isA(const void * ClassID)214b5701710SAlex Langford bool isA(const void *ClassID) const override { 215b5701710SAlex Langford return ClassID == &ID || LanguageRuntime::isA(ClassID); 216b5701710SAlex Langford } 217b5701710SAlex Langford classof(const LanguageRuntime * runtime)218b5701710SAlex Langford static bool classof(const LanguageRuntime *runtime) { 219b5701710SAlex Langford return runtime->isA(&ID); 220b5701710SAlex Langford } 221b5701710SAlex Langford Get(Process & process)222b5701710SAlex Langford static ObjCLanguageRuntime *Get(Process &process) { 223b5701710SAlex Langford return llvm::cast_or_null<ObjCLanguageRuntime>( 224b5701710SAlex Langford process.GetLanguageRuntime(lldb::eLanguageTypeObjC)); 225b5701710SAlex Langford } 226b5701710SAlex Langford GetTaggedPointerVendor()227b5701710SAlex Langford virtual TaggedPointerVendor *GetTaggedPointerVendor() { return nullptr; } 228b5701710SAlex Langford 229b5701710SAlex Langford typedef std::shared_ptr<EncodingToType> EncodingToTypeSP; 230b5701710SAlex Langford 231b5701710SAlex Langford virtual EncodingToTypeSP GetEncodingToType(); 232b5701710SAlex Langford 233b5701710SAlex Langford virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value); 234b5701710SAlex Langford 235b5701710SAlex Langford ClassDescriptorSP GetNonKVOClassDescriptor(ValueObject &in_value); 236b5701710SAlex Langford 237b5701710SAlex Langford virtual ClassDescriptorSP 238b5701710SAlex Langford GetClassDescriptorFromClassName(ConstString class_name); 239b5701710SAlex Langford 240b5701710SAlex Langford virtual ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa); 241b5701710SAlex Langford 242b5701710SAlex Langford ClassDescriptorSP GetNonKVOClassDescriptor(ObjCISA isa); 243b5701710SAlex Langford GetLanguageType()244b5701710SAlex Langford lldb::LanguageType GetLanguageType() const override { 245b5701710SAlex Langford return lldb::eLanguageTypeObjC; 246b5701710SAlex Langford } 247b5701710SAlex Langford 248b5701710SAlex Langford virtual bool IsModuleObjCLibrary(const lldb::ModuleSP &module_sp) = 0; 249b5701710SAlex Langford 250b5701710SAlex Langford virtual bool ReadObjCLibrary(const lldb::ModuleSP &module_sp) = 0; 251b5701710SAlex Langford 252b5701710SAlex Langford virtual bool HasReadObjCLibrary() = 0; 253b5701710SAlex Langford 254833882b3SJim Ingham // These two methods actually use different caches. The only time we'll 255833882b3SJim Ingham // cache a sel_str is if we found a "selector specific stub" for the selector 256833882b3SJim Ingham // and conversely we only add to the SEL cache if we saw a regular dispatch. 257b5701710SAlex Langford lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, lldb::addr_t sel); 258833882b3SJim Ingham lldb::addr_t LookupInMethodCache(lldb::addr_t class_addr, 259833882b3SJim Ingham llvm::StringRef sel_str); 260b5701710SAlex Langford 261b5701710SAlex Langford void AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t sel, 262b5701710SAlex Langford lldb::addr_t impl_addr); 263b5701710SAlex Langford 264833882b3SJim Ingham void AddToMethodCache(lldb::addr_t class_addr, llvm::StringRef sel_str, 265833882b3SJim Ingham lldb::addr_t impl_addr); 266833882b3SJim Ingham 267b5701710SAlex Langford TypeAndOrName LookupInClassNameCache(lldb::addr_t class_addr); 268b5701710SAlex Langford 269b5701710SAlex Langford void AddToClassNameCache(lldb::addr_t class_addr, const char *name, 270b5701710SAlex Langford lldb::TypeSP type_sp); 271b5701710SAlex Langford 272b5701710SAlex Langford void AddToClassNameCache(lldb::addr_t class_addr, 273b5701710SAlex Langford const TypeAndOrName &class_or_type_name); 274b5701710SAlex Langford 275b5701710SAlex Langford lldb::TypeSP LookupInCompleteClassCache(ConstString &name); 276b5701710SAlex Langford 2772fe83274SKazu Hirata std::optional<CompilerType> GetRuntimeType(CompilerType base_type) override; 278b5701710SAlex Langford 279de346cf2SJonas Devlieghere virtual llvm::Expected<std::unique_ptr<UtilityFunction>> 280de346cf2SJonas Devlieghere CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) = 0; 281b5701710SAlex Langford GetRuntimeVersion()282b5701710SAlex Langford virtual ObjCRuntimeVersions GetRuntimeVersion() const { 283b5701710SAlex Langford return ObjCRuntimeVersions::eObjC_VersionUnknown; 284b5701710SAlex Langford } 285b5701710SAlex Langford IsValidISA(ObjCISA isa)286b5701710SAlex Langford bool IsValidISA(ObjCISA isa) { 287b5701710SAlex Langford UpdateISAToDescriptorMap(); 288b5701710SAlex Langford return m_isa_to_descriptor.count(isa) > 0; 289b5701710SAlex Langford } 290b5701710SAlex Langford 291b5701710SAlex Langford virtual void UpdateISAToDescriptorMapIfNeeded() = 0; 292b5701710SAlex Langford UpdateISAToDescriptorMap()293b5701710SAlex Langford void UpdateISAToDescriptorMap() { 294b5701710SAlex Langford if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id) { 295b5701710SAlex Langford UpdateISAToDescriptorMapIfNeeded(); 296b5701710SAlex Langford } 297b5701710SAlex Langford } 298b5701710SAlex Langford 299b5701710SAlex Langford virtual ObjCISA GetISA(ConstString name); 300b5701710SAlex Langford 301b5701710SAlex Langford virtual ObjCISA GetParentClass(ObjCISA isa); 302b5701710SAlex Langford 303b5701710SAlex Langford // Finds the byte offset of the child_type ivar in parent_type. If it can't 304b5701710SAlex Langford // find the offset, returns LLDB_INVALID_IVAR_OFFSET. 305b5701710SAlex Langford 306b5701710SAlex Langford virtual size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, 307b5701710SAlex Langford const char *ivar_name); 308b5701710SAlex Langford HasNewLiteralsAndIndexing()309b5701710SAlex Langford bool HasNewLiteralsAndIndexing() { 310b5701710SAlex Langford if (m_has_new_literals_and_indexing == eLazyBoolCalculate) { 311b5701710SAlex Langford if (CalculateHasNewLiteralsAndIndexing()) 312b5701710SAlex Langford m_has_new_literals_and_indexing = eLazyBoolYes; 313b5701710SAlex Langford else 314b5701710SAlex Langford m_has_new_literals_and_indexing = eLazyBoolNo; 315b5701710SAlex Langford } 316b5701710SAlex Langford 317b5701710SAlex Langford return (m_has_new_literals_and_indexing == eLazyBoolYes); 318b5701710SAlex Langford } 319b5701710SAlex Langford SymbolsDidLoad(const ModuleList & module_list)320b5701710SAlex Langford void SymbolsDidLoad(const ModuleList &module_list) override { 321b5701710SAlex Langford m_negative_complete_class_cache.clear(); 322b5701710SAlex Langford } 323b5701710SAlex Langford 324*5e9f247cSJonas Devlieghere std::optional<uint64_t> 325*5e9f247cSJonas Devlieghere GetTypeBitSize(const CompilerType &compiler_type) override; 326b5701710SAlex Langford 327b5701710SAlex Langford /// Check whether the name is "self" or "_cmd" and should show up in 328b5701710SAlex Langford /// "frame variable". 329efb328f6SEric Christopher bool IsAllowedRuntimeValue(ConstString name) override; 330b5701710SAlex Langford 331b5701710SAlex Langford protected: 332b5701710SAlex Langford // Classes that inherit from ObjCLanguageRuntime can see and modify these 333b5701710SAlex Langford ObjCLanguageRuntime(Process *process); 334b5701710SAlex Langford CalculateHasNewLiteralsAndIndexing()335b5701710SAlex Langford virtual bool CalculateHasNewLiteralsAndIndexing() { return false; } 336b5701710SAlex Langford ISAIsCached(ObjCISA isa)337b5701710SAlex Langford bool ISAIsCached(ObjCISA isa) const { 338b5701710SAlex Langford return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end(); 339b5701710SAlex Langford } 340b5701710SAlex Langford AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp)341b5701710SAlex Langford bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp) { 342b5701710SAlex Langford if (isa != 0) { 343b5701710SAlex Langford m_isa_to_descriptor[isa] = descriptor_sp; 344b5701710SAlex Langford return true; 345b5701710SAlex Langford } 346b5701710SAlex Langford return false; 347b5701710SAlex Langford } 348b5701710SAlex Langford 349b5701710SAlex Langford bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, 350b5701710SAlex Langford const char *class_name); 351b5701710SAlex Langford AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp,uint32_t class_name_hash)352b5701710SAlex Langford bool AddClass(ObjCISA isa, const ClassDescriptorSP &descriptor_sp, 353b5701710SAlex Langford uint32_t class_name_hash) { 354b5701710SAlex Langford if (isa != 0) { 355b5701710SAlex Langford m_isa_to_descriptor[isa] = descriptor_sp; 356b5701710SAlex Langford m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa)); 357b5701710SAlex Langford return true; 358b5701710SAlex Langford } 359b5701710SAlex Langford return false; 360b5701710SAlex Langford } 361b5701710SAlex Langford 362b5701710SAlex Langford private: 363833882b3SJim Ingham // We keep two maps of <Class,Selector>->Implementation so we don't have 364833882b3SJim Ingham // to call the resolver function over and over. 365833882b3SJim Ingham // The first comes from regular obj_msgSend type dispatch, and maps the 366833882b3SJim Ingham // class + uniqued SEL value to an implementation. 367833882b3SJim Ingham // The second comes from the "selector-specific stubs", which are always 368833882b3SJim Ingham // of the form _objc_msgSend$SelectorName, so we don't know the uniqued 369833882b3SJim Ingham // selector, only the string name. 370b5701710SAlex Langford 371b5701710SAlex Langford // FIXME: We need to watch for the loading of Protocols, and flush the cache 372b5701710SAlex Langford // for any 373b5701710SAlex Langford // class that we see so changed. 374b5701710SAlex Langford 375b5701710SAlex Langford struct ClassAndSel { 376833882b3SJim Ingham ClassAndSel() = default; 377b5701710SAlex Langford ClassAndSelClassAndSel378833882b3SJim Ingham ClassAndSel(lldb::addr_t in_class_addr, lldb::addr_t in_sel_addr) 379b5701710SAlex Langford : class_addr(in_class_addr), sel_addr(in_sel_addr) {} 380b5701710SAlex Langford 381b5701710SAlex Langford bool operator==(const ClassAndSel &rhs) { 382b5701710SAlex Langford if (class_addr == rhs.class_addr && sel_addr == rhs.sel_addr) 383b5701710SAlex Langford return true; 384b5701710SAlex Langford else 385b5701710SAlex Langford return false; 386b5701710SAlex Langford } 387b5701710SAlex Langford 388b5701710SAlex Langford bool operator<(const ClassAndSel &rhs) const { 389b5701710SAlex Langford if (class_addr < rhs.class_addr) 390b5701710SAlex Langford return true; 391b5701710SAlex Langford else if (class_addr > rhs.class_addr) 392b5701710SAlex Langford return false; 393b5701710SAlex Langford else { 394b5701710SAlex Langford if (sel_addr < rhs.sel_addr) 395b5701710SAlex Langford return true; 396b5701710SAlex Langford else 397b5701710SAlex Langford return false; 398b5701710SAlex Langford } 399b5701710SAlex Langford } 400b5701710SAlex Langford 401833882b3SJim Ingham lldb::addr_t class_addr = LLDB_INVALID_ADDRESS; 402833882b3SJim Ingham lldb::addr_t sel_addr = LLDB_INVALID_ADDRESS; 403833882b3SJim Ingham }; 404833882b3SJim Ingham 405833882b3SJim Ingham struct ClassAndSelStr { 406833882b3SJim Ingham ClassAndSelStr() = default; 407833882b3SJim Ingham ClassAndSelStrClassAndSelStr408833882b3SJim Ingham ClassAndSelStr(lldb::addr_t in_class_addr, llvm::StringRef in_sel_name) 409833882b3SJim Ingham : class_addr(in_class_addr), sel_name(in_sel_name) {} 410833882b3SJim Ingham 411833882b3SJim Ingham bool operator==(const ClassAndSelStr &rhs) { 412833882b3SJim Ingham return class_addr == rhs.class_addr && sel_name == rhs.sel_name; 413833882b3SJim Ingham } 414833882b3SJim Ingham 415833882b3SJim Ingham bool operator<(const ClassAndSelStr &rhs) const { 416833882b3SJim Ingham if (class_addr < rhs.class_addr) 417833882b3SJim Ingham return true; 418833882b3SJim Ingham else if (class_addr > rhs.class_addr) 419833882b3SJim Ingham return false; 420833882b3SJim Ingham else 421833882b3SJim Ingham return ConstString::Compare(sel_name, rhs.sel_name); 422833882b3SJim Ingham } 423833882b3SJim Ingham 424833882b3SJim Ingham lldb::addr_t class_addr = LLDB_INVALID_ADDRESS; 425833882b3SJim Ingham ConstString sel_name; 426b5701710SAlex Langford }; 427b5701710SAlex Langford 428b5701710SAlex Langford typedef std::map<ClassAndSel, lldb::addr_t> MsgImplMap; 429833882b3SJim Ingham typedef std::map<ClassAndSelStr, lldb::addr_t> MsgImplStrMap; 430b5701710SAlex Langford typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; 431b5701710SAlex Langford typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; 432b5701710SAlex Langford typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; 433b5701710SAlex Langford typedef HashToISAMap::iterator HashToISAIterator; 434b5701710SAlex Langford typedef ThreadSafeDenseMap<void *, uint64_t> TypeSizeCache; 435b5701710SAlex Langford 436b5701710SAlex Langford MsgImplMap m_impl_cache; 437833882b3SJim Ingham MsgImplStrMap m_impl_str_cache; 438b5701710SAlex Langford LazyBool m_has_new_literals_and_indexing; 439b5701710SAlex Langford ISAToDescriptorMap m_isa_to_descriptor; 440b5701710SAlex Langford HashToISAMap m_hash_to_isa_map; 441b5701710SAlex Langford TypeSizeCache m_type_size_cache; 442b5701710SAlex Langford 443b5701710SAlex Langford protected: 444b5701710SAlex Langford uint32_t m_isa_to_descriptor_stop_id; 445b5701710SAlex Langford 446b5701710SAlex Langford typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; 447b5701710SAlex Langford CompleteClassMap m_complete_class_cache; 448b5701710SAlex Langford 449b5701710SAlex Langford struct ConstStringSetHelpers { operatorConstStringSetHelpers450b5701710SAlex Langford size_t operator()(ConstString arg) const // for hashing 451b5701710SAlex Langford { 452b5701710SAlex Langford return (size_t)arg.GetCString(); 453b5701710SAlex Langford } operatorConstStringSetHelpers454b5701710SAlex Langford bool operator()(ConstString arg1, 455b5701710SAlex Langford ConstString arg2) const // for equality 456b5701710SAlex Langford { 457b5701710SAlex Langford return arg1.operator==(arg2); 458b5701710SAlex Langford } 459b5701710SAlex Langford }; 460b5701710SAlex Langford typedef std::unordered_set<ConstString, ConstStringSetHelpers, 461b5701710SAlex Langford ConstStringSetHelpers> 462b5701710SAlex Langford CompleteClassSet; 463b5701710SAlex Langford CompleteClassSet m_negative_complete_class_cache; 464b5701710SAlex Langford 465b5701710SAlex Langford ISAToDescriptorIterator GetDescriptorIterator(ConstString name); 466b5701710SAlex Langford 467b5701710SAlex Langford friend class ::CommandObjectObjC_ClassTable_Dump; 468b5701710SAlex Langford 469b5701710SAlex Langford std::pair<ISAToDescriptorIterator, ISAToDescriptorIterator> 470b5701710SAlex Langford GetDescriptorIteratorPair(bool update_if_needed = true); 471b5701710SAlex Langford 472b5701710SAlex Langford void ReadObjCLibraryIfNeeded(const ModuleList &module_list); 473b5701710SAlex Langford 474eaebcbc6SKonrad Kleine ObjCLanguageRuntime(const ObjCLanguageRuntime &) = delete; 475eaebcbc6SKonrad Kleine const ObjCLanguageRuntime &operator=(const ObjCLanguageRuntime &) = delete; 476b5701710SAlex Langford }; 477b5701710SAlex Langford 478b5701710SAlex Langford } // namespace lldb_private 479b5701710SAlex Langford 480cdc514e4SJonas Devlieghere #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_OBJCLANGUAGERUNTIME_H 481