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