1 //===-- AppleObjCRuntimeV2.h ------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef liblldb_AppleObjCRuntimeV2_h_ 10 #define liblldb_AppleObjCRuntimeV2_h_ 11 12 #include <map> 13 #include <memory> 14 #include <mutex> 15 16 #include "AppleObjCRuntime.h" 17 #include "lldb/lldb-private.h" 18 19 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" 20 21 class RemoteNXMapTable; 22 23 namespace lldb_private { 24 25 class AppleObjCRuntimeV2 : public AppleObjCRuntime { 26 public: 27 ~AppleObjCRuntimeV2() override = default; 28 29 // Static Functions 30 static void Initialize(); 31 32 static void Terminate(); 33 34 static lldb_private::LanguageRuntime * 35 CreateInstance(Process *process, lldb::LanguageType language); 36 37 static lldb_private::ConstString GetPluginNameStatic(); 38 39 static char ID; 40 41 bool isA(const void *ClassID) const override { 42 return ClassID == &ID || AppleObjCRuntime::isA(ClassID); 43 } 44 45 static bool classof(const LanguageRuntime *runtime) { 46 return runtime->isA(&ID); 47 } 48 49 // These are generic runtime functions: 50 bool GetDynamicTypeAndAddress(ValueObject &in_value, 51 lldb::DynamicValueType use_dynamic, 52 TypeAndOrName &class_type_or_name, 53 Address &address, 54 Value::ValueType &value_type) override; 55 56 UtilityFunction *CreateObjectChecker(const char *) override; 57 58 // PluginInterface protocol 59 ConstString GetPluginName() override; 60 61 uint32_t GetPluginVersion() override; 62 63 ObjCRuntimeVersions GetRuntimeVersion() const override { 64 return ObjCRuntimeVersions::eAppleObjC_V2; 65 } 66 67 size_t GetByteOffsetForIvar(CompilerType &parent_qual_type, 68 const char *ivar_name) override; 69 70 void UpdateISAToDescriptorMapIfNeeded() override; 71 72 ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override; 73 74 ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override; 75 76 DeclVendor *GetDeclVendor() override; 77 78 lldb::addr_t LookupRuntimeSymbol(ConstString name) override; 79 80 EncodingToTypeSP GetEncodingToType() override; 81 82 bool IsTaggedPointer(lldb::addr_t ptr) override; 83 84 TaggedPointerVendor *GetTaggedPointerVendor() override { 85 return m_tagged_pointer_vendor_up.get(); 86 } 87 88 lldb::addr_t GetTaggedPointerObfuscator(); 89 90 void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, 91 lldb::addr_t &cf_false) override; 92 93 // none of these are valid ISAs - we use them to infer the type 94 // of tagged pointers - if we have something meaningful to say 95 // we report an actual type - otherwise, we just say tagged 96 // there is no connection between the values here and the tagged pointers map 97 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1; 98 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2; 99 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3; 100 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4; 101 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 102 5; 103 static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6; 104 105 protected: 106 lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, 107 bool catch_bp, 108 bool throw_bp) override; 109 110 private: 111 class HashTableSignature { 112 public: 113 HashTableSignature(); 114 115 bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime, 116 RemoteNXMapTable &hash_table); 117 118 void UpdateSignature(const RemoteNXMapTable &hash_table); 119 120 protected: 121 uint32_t m_count; 122 uint32_t m_num_buckets; 123 lldb::addr_t m_buckets_ptr; 124 }; 125 126 class NonPointerISACache { 127 public: 128 static NonPointerISACache * 129 CreateInstance(AppleObjCRuntimeV2 &runtime, 130 const lldb::ModuleSP &objc_module_sp); 131 132 ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa); 133 134 private: 135 NonPointerISACache(AppleObjCRuntimeV2 &runtime, 136 const lldb::ModuleSP &objc_module_sp, 137 uint64_t objc_debug_isa_class_mask, 138 uint64_t objc_debug_isa_magic_mask, 139 uint64_t objc_debug_isa_magic_value, 140 uint64_t objc_debug_indexed_isa_magic_mask, 141 uint64_t objc_debug_indexed_isa_magic_value, 142 uint64_t objc_debug_indexed_isa_index_mask, 143 uint64_t objc_debug_indexed_isa_index_shift, 144 lldb::addr_t objc_indexed_classes); 145 146 bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa); 147 148 AppleObjCRuntimeV2 &m_runtime; 149 std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache; 150 lldb::ModuleWP m_objc_module_wp; 151 uint64_t m_objc_debug_isa_class_mask; 152 uint64_t m_objc_debug_isa_magic_mask; 153 uint64_t m_objc_debug_isa_magic_value; 154 155 uint64_t m_objc_debug_indexed_isa_magic_mask; 156 uint64_t m_objc_debug_indexed_isa_magic_value; 157 uint64_t m_objc_debug_indexed_isa_index_mask; 158 uint64_t m_objc_debug_indexed_isa_index_shift; 159 lldb::addr_t m_objc_indexed_classes; 160 161 std::vector<lldb::addr_t> m_indexed_isa_cache; 162 163 friend class AppleObjCRuntimeV2; 164 165 DISALLOW_COPY_AND_ASSIGN(NonPointerISACache); 166 }; 167 168 class TaggedPointerVendorV2 169 : public ObjCLanguageRuntime::TaggedPointerVendor { 170 public: 171 ~TaggedPointerVendorV2() override = default; 172 173 static TaggedPointerVendorV2 * 174 CreateInstance(AppleObjCRuntimeV2 &runtime, 175 const lldb::ModuleSP &objc_module_sp); 176 177 protected: 178 AppleObjCRuntimeV2 &m_runtime; 179 180 TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime) 181 : TaggedPointerVendor(), m_runtime(runtime) {} 182 183 private: 184 DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorV2); 185 }; 186 187 class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 { 188 public: 189 bool IsPossibleTaggedPointer(lldb::addr_t ptr) override; 190 191 ObjCLanguageRuntime::ClassDescriptorSP 192 GetClassDescriptor(lldb::addr_t ptr) override; 193 194 protected: 195 TaggedPointerVendorRuntimeAssisted( 196 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 197 uint32_t objc_debug_taggedpointer_slot_shift, 198 uint32_t objc_debug_taggedpointer_slot_mask, 199 uint32_t objc_debug_taggedpointer_payload_lshift, 200 uint32_t objc_debug_taggedpointer_payload_rshift, 201 lldb::addr_t objc_debug_taggedpointer_classes); 202 203 typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache; 204 typedef Cache::iterator CacheIterator; 205 Cache m_cache; 206 uint64_t m_objc_debug_taggedpointer_mask; 207 uint32_t m_objc_debug_taggedpointer_slot_shift; 208 uint32_t m_objc_debug_taggedpointer_slot_mask; 209 uint32_t m_objc_debug_taggedpointer_payload_lshift; 210 uint32_t m_objc_debug_taggedpointer_payload_rshift; 211 lldb::addr_t m_objc_debug_taggedpointer_classes; 212 213 friend class AppleObjCRuntimeV2::TaggedPointerVendorV2; 214 215 DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted); 216 }; 217 218 class TaggedPointerVendorExtended 219 : public TaggedPointerVendorRuntimeAssisted { 220 public: 221 ObjCLanguageRuntime::ClassDescriptorSP 222 GetClassDescriptor(lldb::addr_t ptr) override; 223 224 protected: 225 TaggedPointerVendorExtended( 226 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 227 uint64_t objc_debug_taggedpointer_ext_mask, 228 uint32_t objc_debug_taggedpointer_slot_shift, 229 uint32_t objc_debug_taggedpointer_ext_slot_shift, 230 uint32_t objc_debug_taggedpointer_slot_mask, 231 uint32_t objc_debug_taggedpointer_ext_slot_mask, 232 uint32_t objc_debug_taggedpointer_payload_lshift, 233 uint32_t objc_debug_taggedpointer_payload_rshift, 234 uint32_t objc_debug_taggedpointer_ext_payload_lshift, 235 uint32_t objc_debug_taggedpointer_ext_payload_rshift, 236 lldb::addr_t objc_debug_taggedpointer_classes, 237 lldb::addr_t objc_debug_taggedpointer_ext_classes); 238 239 bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr); 240 241 typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache; 242 typedef Cache::iterator CacheIterator; 243 Cache m_ext_cache; 244 uint64_t m_objc_debug_taggedpointer_ext_mask; 245 uint32_t m_objc_debug_taggedpointer_ext_slot_shift; 246 uint32_t m_objc_debug_taggedpointer_ext_slot_mask; 247 uint32_t m_objc_debug_taggedpointer_ext_payload_lshift; 248 uint32_t m_objc_debug_taggedpointer_ext_payload_rshift; 249 lldb::addr_t m_objc_debug_taggedpointer_ext_classes; 250 251 friend class AppleObjCRuntimeV2::TaggedPointerVendorV2; 252 253 DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended); 254 }; 255 256 class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 { 257 public: 258 bool IsPossibleTaggedPointer(lldb::addr_t ptr) override; 259 260 ObjCLanguageRuntime::ClassDescriptorSP 261 GetClassDescriptor(lldb::addr_t ptr) override; 262 263 protected: 264 TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime) 265 : TaggedPointerVendorV2(runtime) {} 266 267 friend class AppleObjCRuntimeV2::TaggedPointerVendorV2; 268 269 DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy); 270 }; 271 272 struct DescriptorMapUpdateResult { 273 bool m_update_ran; 274 uint32_t m_num_found; 275 276 DescriptorMapUpdateResult(bool ran, uint32_t found) { 277 m_update_ran = ran; 278 m_num_found = found; 279 } 280 281 static DescriptorMapUpdateResult Fail() { return {false, 0}; } 282 283 static DescriptorMapUpdateResult Success(uint32_t found) { 284 return {true, found}; 285 } 286 }; 287 288 AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp); 289 290 ObjCISA GetPointerISA(ObjCISA isa); 291 292 lldb::addr_t GetISAHashTablePointer(); 293 294 bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table); 295 296 DescriptorMapUpdateResult 297 UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table); 298 299 uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data, 300 uint32_t num_class_infos); 301 302 DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache(); 303 304 enum class SharedCacheWarningReason { 305 eExpressionExecutionFailure, 306 eNotEnoughClassesRead 307 }; 308 309 void WarnIfNoClassesCached(SharedCacheWarningReason reason); 310 311 lldb::addr_t GetSharedCacheReadOnlyAddress(); 312 313 bool GetCFBooleanValuesIfNeeded(); 314 315 friend class ClassDescriptorV2; 316 317 std::unique_ptr<UtilityFunction> m_get_class_info_code; 318 lldb::addr_t m_get_class_info_args; 319 std::mutex m_get_class_info_args_mutex; 320 321 std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code; 322 lldb::addr_t m_get_shared_cache_class_info_args; 323 std::mutex m_get_shared_cache_class_info_args_mutex; 324 325 std::unique_ptr<DeclVendor> m_decl_vendor_up; 326 lldb::addr_t m_tagged_pointer_obfuscator; 327 lldb::addr_t m_isa_hash_table_ptr; 328 HashTableSignature m_hash_signature; 329 bool m_has_object_getClass; 330 bool m_loaded_objc_opt; 331 std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up; 332 std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up; 333 EncodingToTypeSP m_encoding_to_type_sp; 334 bool m_noclasses_warning_emitted; 335 llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values; 336 }; 337 338 } // namespace lldb_private 339 340 #endif // liblldb_AppleObjCRuntimeV2_h_ 341