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 <unordered_set> 18 19 // Other libraries and framework includes 20 // Project includes 21 #include "lldb/lldb-private.h" 22 #include "lldb/Core/PluginInterface.h" 23 #include "lldb/Symbol/Type.h" 24 #include "lldb/Symbol/TypeVendor.h" 25 #include "lldb/Target/LanguageRuntime.h" 26 27 namespace lldb_private { 28 29 class ClangUtilityFunction; 30 31 class ObjCLanguageRuntime : 32 public LanguageRuntime 33 { 34 public: 35 class MethodName 36 { 37 public: 38 enum Type 39 { 40 eTypeUnspecified, 41 eTypeClassMethod, 42 eTypeInstanceMethod 43 }; 44 MethodName()45 MethodName () : 46 m_full(), 47 m_class(), 48 m_category(), 49 m_selector(), 50 m_type (eTypeUnspecified), 51 m_category_is_valid (false) 52 { 53 } 54 MethodName(const char * name,bool strict)55 MethodName (const char *name, bool strict) : 56 m_full(), 57 m_class(), 58 m_category(), 59 m_selector(), 60 m_type (eTypeUnspecified), 61 m_category_is_valid (false) 62 { 63 SetName (name, strict); 64 } 65 66 void 67 Clear(); 68 69 bool IsValid(bool strict)70 IsValid (bool strict) const 71 { 72 // If "strict" is true, the name must have everything specified including 73 // the leading "+" or "-" on the method name 74 if (strict && m_type == eTypeUnspecified) 75 return false; 76 // Other than that, m_full will only be filled in if the objective C 77 // name is valid. 78 return (bool)m_full; 79 } 80 81 bool HasCategory()82 HasCategory() 83 { 84 return (bool)GetCategory(); 85 } 86 87 Type GetType()88 GetType () const 89 { 90 return m_type; 91 } 92 93 const ConstString & GetFullName()94 GetFullName () const 95 { 96 return m_full; 97 } 98 99 ConstString 100 GetFullNameWithoutCategory (bool empty_if_no_category); 101 102 bool 103 SetName (const char *name, bool strict); 104 105 const ConstString & 106 GetClassName (); 107 108 const ConstString & 109 GetClassNameWithCategory (); 110 111 const ConstString & 112 GetCategory (); 113 114 const ConstString & 115 GetSelector (); 116 117 // Get all possible names for a method. Examples: 118 // If name is "+[NSString(my_additions) myStringWithCString:]" 119 // names[0] => "+[NSString(my_additions) myStringWithCString:]" 120 // names[1] => "+[NSString myStringWithCString:]" 121 // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]" 122 // names[0] => "+[NSString(my_additions) myStringWithCString:]" 123 // names[1] => "-[NSString(my_additions) myStringWithCString:]" 124 // names[2] => "+[NSString myStringWithCString:]" 125 // names[3] => "-[NSString myStringWithCString:]" 126 size_t 127 GetFullNames (std::vector<ConstString> &names, bool append); 128 protected: 129 ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]" 130 ConstString m_class; // Class name: "NSString" 131 ConstString m_class_category; // Class with category: "NSString(my_additions)" 132 ConstString m_category; // Category: "my_additions" 133 ConstString m_selector; // Selector: "myStringWithCString:" 134 Type m_type; 135 bool m_category_is_valid; 136 137 }; 138 typedef lldb::addr_t ObjCISA; 139 140 class ClassDescriptor; 141 typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP; 142 143 // the information that we want to support retrieving from an ObjC class 144 // this needs to be pure virtual since there are at least 2 different implementations 145 // of the runtime, and more might come 146 class ClassDescriptor 147 { 148 public: 149 ClassDescriptor()150 ClassDescriptor() : 151 m_is_kvo (eLazyBoolCalculate), 152 m_is_cf (eLazyBoolCalculate), 153 m_type_wp () 154 { 155 } 156 157 virtual ~ClassDescriptor()158 ~ClassDescriptor () 159 { 160 } 161 162 virtual ConstString 163 GetClassName () = 0; 164 165 virtual ClassDescriptorSP 166 GetSuperclass () = 0; 167 168 // virtual if any implementation has some other version-specific rules 169 // but for the known v1/v2 this is all that needs to be done 170 virtual bool IsKVO()171 IsKVO () 172 { 173 if (m_is_kvo == eLazyBoolCalculate) 174 { 175 const char* class_name = GetClassName().AsCString(); 176 if (class_name && *class_name) 177 m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name); 178 } 179 return (m_is_kvo == eLazyBoolYes); 180 } 181 182 // virtual if any implementation has some other version-specific rules 183 // but for the known v1/v2 this is all that needs to be done 184 virtual bool IsCFType()185 IsCFType () 186 { 187 if (m_is_cf == eLazyBoolCalculate) 188 { 189 const char* class_name = GetClassName().AsCString(); 190 if (class_name && *class_name) 191 m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 || 192 strcmp(class_name,"NSCFType") == 0); 193 } 194 return (m_is_cf == eLazyBoolYes); 195 } 196 197 virtual bool 198 IsValid () = 0; 199 200 virtual bool 201 GetTaggedPointerInfo (uint64_t* info_bits = NULL, 202 uint64_t* value_bits = NULL, 203 uint64_t* payload = NULL) = 0; 204 205 virtual uint64_t 206 GetInstanceSize () = 0; 207 208 // use to implement version-specific additional constraints on pointers 209 virtual bool CheckPointer(lldb::addr_t value,uint32_t ptr_size)210 CheckPointer (lldb::addr_t value, 211 uint32_t ptr_size) const 212 { 213 return true; 214 } 215 216 virtual ObjCISA 217 GetISA () = 0; 218 219 // This should return true iff the interface could be completed 220 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)221 Describe (std::function <void (ObjCISA)> const &superclass_func, 222 std::function <bool (const char*, const char*)> const &instance_method_func, 223 std::function <bool (const char*, const char*)> const &class_method_func, 224 std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) 225 { 226 return false; 227 } 228 229 lldb::TypeSP GetType()230 GetType () 231 { 232 return m_type_wp.lock(); 233 } 234 235 void SetType(const lldb::TypeSP & type_sp)236 SetType (const lldb::TypeSP &type_sp) 237 { 238 m_type_wp = type_sp; 239 } 240 241 protected: 242 bool 243 IsPointerValid (lldb::addr_t value, 244 uint32_t ptr_size, 245 bool allow_NULLs = false, 246 bool allow_tagged = false, 247 bool check_version_specific = false) const; 248 249 private: 250 LazyBool m_is_kvo; 251 LazyBool m_is_cf; 252 lldb::TypeWP m_type_wp; 253 }; 254 255 virtual ClassDescriptorSP 256 GetClassDescriptor (ValueObject& in_value); 257 258 ClassDescriptorSP 259 GetNonKVOClassDescriptor (ValueObject& in_value); 260 261 virtual ClassDescriptorSP 262 GetClassDescriptorFromClassName (const ConstString &class_name); 263 264 virtual ClassDescriptorSP 265 GetClassDescriptorFromISA (ObjCISA isa); 266 267 ClassDescriptorSP 268 GetNonKVOClassDescriptor (ObjCISA isa); 269 270 virtual 271 ~ObjCLanguageRuntime(); 272 273 virtual lldb::LanguageType GetLanguageType()274 GetLanguageType () const 275 { 276 return lldb::eLanguageTypeObjC; 277 } 278 279 virtual bool 280 IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 281 282 virtual bool 283 ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 284 285 virtual bool 286 HasReadObjCLibrary () = 0; 287 288 virtual lldb::ThreadPlanSP 289 GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0; 290 291 lldb::addr_t 292 LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel); 293 294 void 295 AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr); 296 297 TypeAndOrName 298 LookupInClassNameCache (lldb::addr_t class_addr); 299 300 void 301 AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp); 302 303 void 304 AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name); 305 306 lldb::TypeSP 307 LookupInCompleteClassCache (ConstString &name); 308 309 virtual ClangUtilityFunction * 310 CreateObjectChecker (const char *) = 0; 311 312 virtual ObjCRuntimeVersions GetRuntimeVersion()313 GetRuntimeVersion () 314 { 315 return eObjC_VersionUnknown; 316 } 317 318 bool IsValidISA(ObjCISA isa)319 IsValidISA(ObjCISA isa) 320 { 321 UpdateISAToDescriptorMap(); 322 return m_isa_to_descriptor.count(isa) > 0; 323 } 324 325 virtual void 326 UpdateISAToDescriptorMapIfNeeded() = 0; 327 328 void UpdateISAToDescriptorMap()329 UpdateISAToDescriptorMap() 330 { 331 if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id) 332 { 333 UpdateISAToDescriptorMapIfNeeded (); 334 } 335 } 336 337 virtual ObjCISA 338 GetISA(const ConstString &name); 339 340 virtual ConstString 341 GetActualTypeName(ObjCISA isa); 342 343 virtual ObjCISA 344 GetParentClass(ObjCISA isa); 345 346 virtual TypeVendor * GetTypeVendor()347 GetTypeVendor() 348 { 349 return NULL; 350 } 351 352 // Finds the byte offset of the child_type ivar in parent_type. If it can't find the 353 // offset, returns LLDB_INVALID_IVAR_OFFSET. 354 355 virtual size_t 356 GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); 357 358 // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol), 359 // try to determine from the runtime what the value of that symbol would be. 360 // Useful when the underlying binary is stripped. 361 virtual lldb::addr_t LookupRuntimeSymbol(const ConstString & name)362 LookupRuntimeSymbol (const ConstString &name) 363 { 364 return LLDB_INVALID_ADDRESS; 365 } 366 367 //------------------------------------------------------------------ 368 /// Chop up an objective C function prototype. 369 /// 370 /// Chop up an objective C function fullname and optionally fill in 371 /// any non-NULL ConstString objects. If a ConstString * is NULL, 372 /// then this name doesn't get filled in 373 /// 374 /// @param[in] name 375 /// A fully specified objective C function name. The string might 376 /// contain a category and it includes the leading "+" or "-" and 377 /// the square brackets, no types for the arguments, just the plain 378 /// selector. A few examples: 379 /// "-[NSStringDrawingContext init]" 380 /// "-[NSStringDrawingContext addString:inRect:]" 381 /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" 382 /// "+[NSString(NSStringDrawing) usesFontLeading]" 383 /// 384 /// @param[out] class_name 385 /// If non-NULL, this string will be filled in with the class 386 /// name including the category. The examples above would return: 387 /// "NSStringDrawingContext" 388 /// "NSStringDrawingContext" 389 /// "NSString(NSStringDrawing)" 390 /// "NSString(NSStringDrawing)" 391 /// 392 /// @param[out] selector_name 393 /// If non-NULL, this string will be filled in with the selector 394 /// name. The examples above would return: 395 /// "init" 396 /// "addString:inRect:" 397 /// "sizeWithAttributes:" 398 /// "usesFontLeading" 399 /// 400 /// @param[out] name_sans_category 401 /// If non-NULL, this string will be filled in with the class 402 /// name _without_ the category. If there is no category, and empty 403 /// string will be returned (as the result would be normally returned 404 /// in the "class_name" argument). The examples above would return: 405 /// <empty> 406 /// <empty> 407 /// "-[NSString sizeWithAttributes:]" 408 /// "+[NSString usesFontLeading]" 409 /// 410 /// @param[out] class_name_sans_category 411 /// If non-NULL, this string will be filled in with the prototype 412 /// name _without_ the category. If there is no category, and empty 413 /// string will be returned (as this is already the value that was 414 /// passed in). The examples above would return: 415 /// <empty> 416 /// <empty> 417 /// "NSString" 418 /// "NSString" 419 /// 420 /// @return 421 /// Returns the number of strings that were successfully filled 422 /// in. 423 //------------------------------------------------------------------ 424 // static uint32_t 425 // ParseMethodName (const char *name, 426 // ConstString *class_name, // Class name (with category if there is one) 427 // ConstString *selector_name, // selector only 428 // ConstString *name_sans_category, // full function name with no category (empty if no category) 429 // ConstString *class_name_sans_category);// Class name without category (empty if no category) 430 431 static bool IsPossibleObjCMethodName(const char * name)432 IsPossibleObjCMethodName (const char *name) 433 { 434 if (!name) 435 return false; 436 bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; 437 bool ends_right = (name[strlen(name) - 1] == ']'); 438 return (starts_right && ends_right); 439 } 440 441 static bool IsPossibleObjCSelector(const char * name)442 IsPossibleObjCSelector (const char *name) 443 { 444 if (!name) 445 return false; 446 447 if (strchr(name, ':') == NULL) 448 return true; 449 else if (name[strlen(name) - 1] == ':') 450 return true; 451 else 452 return false; 453 } 454 455 bool HasNewLiteralsAndIndexing()456 HasNewLiteralsAndIndexing () 457 { 458 if (m_has_new_literals_and_indexing == eLazyBoolCalculate) 459 { 460 if (CalculateHasNewLiteralsAndIndexing()) 461 m_has_new_literals_and_indexing = eLazyBoolYes; 462 else 463 m_has_new_literals_and_indexing = eLazyBoolNo; 464 } 465 466 return (m_has_new_literals_and_indexing == eLazyBoolYes); 467 } 468 469 virtual void SymbolsDidLoad(const ModuleList & module_list)470 SymbolsDidLoad (const ModuleList& module_list) 471 { 472 m_negative_complete_class_cache.clear(); 473 } 474 475 protected: 476 //------------------------------------------------------------------ 477 // Classes that inherit from ObjCLanguageRuntime can see and modify these 478 //------------------------------------------------------------------ 479 ObjCLanguageRuntime(Process *process); 480 CalculateHasNewLiteralsAndIndexing()481 virtual bool CalculateHasNewLiteralsAndIndexing() 482 { 483 return false; 484 } 485 486 487 bool ISAIsCached(ObjCISA isa)488 ISAIsCached (ObjCISA isa) const 489 { 490 return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end(); 491 } 492 493 bool AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp)494 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp) 495 { 496 if (isa != 0) 497 { 498 m_isa_to_descriptor[isa] = descriptor_sp; 499 return true; 500 } 501 return false; 502 } 503 504 bool 505 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name); 506 507 bool AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp,uint32_t class_name_hash)508 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash) 509 { 510 if (isa != 0) 511 { 512 m_isa_to_descriptor[isa] = descriptor_sp; 513 m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa)); 514 return true; 515 } 516 return false; 517 } 518 519 private: 520 // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver 521 // function over and over. 522 523 // FIXME: We need to watch for the loading of Protocols, and flush the cache for any 524 // class that we see so changed. 525 526 struct ClassAndSel 527 { ClassAndSelClassAndSel528 ClassAndSel() 529 { 530 sel_addr = LLDB_INVALID_ADDRESS; 531 class_addr = LLDB_INVALID_ADDRESS; 532 } ClassAndSelClassAndSel533 ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) : 534 class_addr (in_class_addr), 535 sel_addr(in_sel_addr) 536 { 537 } 538 bool operator== (const ClassAndSel &rhs) 539 { 540 if (class_addr == rhs.class_addr 541 && sel_addr == rhs.sel_addr) 542 return true; 543 else 544 return false; 545 } 546 547 bool operator< (const ClassAndSel &rhs) const 548 { 549 if (class_addr < rhs.class_addr) 550 return true; 551 else if (class_addr > rhs.class_addr) 552 return false; 553 else 554 { 555 if (sel_addr < rhs.sel_addr) 556 return true; 557 else 558 return false; 559 } 560 } 561 562 lldb::addr_t class_addr; 563 lldb::addr_t sel_addr; 564 }; 565 566 typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap; 567 typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; 568 typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; 569 typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; 570 typedef HashToISAMap::iterator HashToISAIterator; 571 572 MsgImplMap m_impl_cache; 573 LazyBool m_has_new_literals_and_indexing; 574 ISAToDescriptorMap m_isa_to_descriptor; 575 HashToISAMap m_hash_to_isa_map; 576 577 protected: 578 uint32_t m_isa_to_descriptor_stop_id; 579 580 typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; 581 CompleteClassMap m_complete_class_cache; 582 583 struct ConstStringSetHelpers { operatorConstStringSetHelpers584 size_t operator () (const ConstString& arg) const // for hashing 585 { 586 return (size_t)arg.GetCString(); 587 } operatorConstStringSetHelpers588 bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality 589 { 590 return arg1.operator==(arg2); 591 } 592 }; 593 typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet; 594 CompleteClassSet m_negative_complete_class_cache; 595 596 ISAToDescriptorIterator 597 GetDescriptorIterator (const ConstString &name); 598 599 DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); 600 }; 601 602 } // namespace lldb_private 603 604 #endif // liblldb_ObjCLanguageRuntime_h_ 605