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