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