ObjCLanguageRuntime.h revision a510437e795477e5f629263d3d191d982c991733
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 18// Other libraries and framework includes 19// Project includes 20#include "lldb/lldb-private.h" 21#include "lldb/Core/PluginInterface.h" 22#include "lldb/Symbol/Type.h" 23#include "lldb/Symbol/TypeVendor.h" 24#include "lldb/Target/LanguageRuntime.h" 25 26namespace lldb_private { 27 28class ClangUtilityFunction; 29 30class ObjCLanguageRuntime : 31 public LanguageRuntime 32{ 33public: 34 35 typedef lldb::addr_t ObjCISA; 36 37 class ClassDescriptor; 38 typedef STD_SHARED_PTR(ClassDescriptor) ClassDescriptorSP; 39 40 // the information that we want to support retrieving from an ObjC class 41 // this needs to be pure virtual since there are at least 2 different implementations 42 // of the runtime, and more might come 43 class ClassDescriptor 44 { 45 public: 46 47 ClassDescriptor() : 48 m_is_kvo(eLazyBoolCalculate), 49 m_is_cf(eLazyBoolCalculate) 50 {} 51 52 ClassDescriptor (ObjCISA isa, lldb::ProcessSP process) : 53 m_is_kvo(eLazyBoolCalculate), 54 m_is_cf(eLazyBoolCalculate) 55 {} 56 57 virtual ConstString 58 GetClassName () = 0; 59 60 virtual ClassDescriptorSP 61 GetSuperclass () = 0; 62 63 // virtual if any implementation has some other version-specific rules 64 // but for the known v1/v2 this is all that needs to be done 65 virtual bool 66 IsKVO () 67 { 68 if (m_is_kvo == eLazyBoolCalculate) 69 { 70 const char* class_name = GetClassName().AsCString(); 71 if (class_name && *class_name) 72 m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name); 73 } 74 return (m_is_kvo == eLazyBoolYes); 75 } 76 77 // virtual if any implementation has some other version-specific rules 78 // but for the known v1/v2 this is all that needs to be done 79 virtual bool 80 IsCFType () 81 { 82 if (m_is_cf == eLazyBoolCalculate) 83 { 84 const char* class_name = GetClassName().AsCString(); 85 if (class_name && *class_name) 86 m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 || 87 strcmp(class_name,"NSCFType") == 0); 88 } 89 return (m_is_cf == eLazyBoolYes); 90 } 91 92 virtual bool 93 IsValid () = 0; 94 95 virtual bool 96 IsTagged () = 0; 97 98 virtual uint64_t 99 GetInstanceSize () = 0; 100 101 // use to implement version-specific additional constraints on pointers 102 virtual bool 103 CheckPointer (lldb::addr_t value, 104 uint32_t ptr_size) const 105 { 106 return true; 107 } 108 109 virtual ObjCISA 110 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 <void (const char*, const char*)> const &instance_method_func, 116 std::function <void (const char*, const char*)> const &class_method_func) 117 { 118 return false; 119 } 120 121 virtual 122 ~ClassDescriptor () 123 {} 124 125 protected: 126 bool 127 IsPointerValid (lldb::addr_t value, 128 uint32_t ptr_size, 129 bool allow_NULLs = false, 130 bool allow_tagged = false, 131 bool check_version_specific = false) const; 132 133 private: 134 LazyBool m_is_kvo; 135 LazyBool m_is_cf; 136 }; 137 138 // a convenience subclass of ClassDescriptor meant to represent invalid objects 139 class ClassDescriptor_Invalid : public ClassDescriptor 140 { 141 public: 142 ClassDescriptor_Invalid() {} 143 144 virtual ConstString 145 GetClassName () { return ConstString(""); } 146 147 virtual ClassDescriptorSP 148 GetSuperclass () { return ClassDescriptorSP(new ClassDescriptor_Invalid()); } 149 150 virtual bool 151 IsValid () { return false; } 152 153 virtual bool 154 IsTagged () { return false; } 155 156 virtual uint64_t 157 GetInstanceSize () { return 0; } 158 159 virtual ObjCISA 160 GetISA () { return 0; } 161 162 virtual bool 163 CheckPointer (lldb::addr_t value, uint32_t ptr_size) const 164 { 165 return false; 166 } 167 168 virtual 169 ~ClassDescriptor_Invalid () 170 {} 171 172 }; 173 174 virtual ClassDescriptorSP 175 GetClassDescriptor (ValueObject& in_value); 176 177 ClassDescriptorSP 178 GetNonKVOClassDescriptor (ValueObject& in_value); 179 180 virtual ClassDescriptorSP 181 GetClassDescriptor (const ConstString &class_name); 182 183 virtual ClassDescriptorSP 184 GetClassDescriptor (ObjCISA isa); 185 186 ClassDescriptorSP 187 GetNonKVOClassDescriptor (ObjCISA isa); 188 189 virtual 190 ~ObjCLanguageRuntime(); 191 192 virtual lldb::LanguageType 193 GetLanguageType () const 194 { 195 return lldb::eLanguageTypeObjC; 196 } 197 198 virtual bool 199 IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 200 201 virtual bool 202 ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 203 204 virtual bool 205 HasReadObjCLibrary () = 0; 206 207 virtual lldb::ThreadPlanSP 208 GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0; 209 210 lldb::addr_t 211 LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel); 212 213 void 214 AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr); 215 216 TypeAndOrName 217 LookupInClassNameCache (lldb::addr_t class_addr); 218 219 void 220 AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp); 221 222 void 223 AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name); 224 225 lldb::TypeSP 226 LookupInCompleteClassCache (ConstString &name); 227 228 virtual ClangUtilityFunction * 229 CreateObjectChecker (const char *) = 0; 230 231 virtual ObjCRuntimeVersions 232 GetRuntimeVersion () 233 { 234 return eObjC_VersionUnknown; 235 } 236 237 bool 238 IsValidISA(ObjCISA isa) 239 { 240 UpdateISAToDescriptorMap(); 241 return m_isa_to_descriptor_cache.count(isa) > 0; 242 } 243 244 virtual bool 245 UpdateISAToDescriptorMap_Impl() = 0; 246 247 void 248 UpdateISAToDescriptorMap() 249 { 250 if (m_isa_to_descriptor_cache_is_up_to_date) 251 return; 252 253 m_isa_to_descriptor_cache_is_up_to_date = UpdateISAToDescriptorMap_Impl(); 254 } 255 256 virtual ObjCISA 257 GetISA(const ConstString &name); 258 259 virtual ConstString 260 GetActualTypeName(ObjCISA isa); 261 262 virtual ObjCISA 263 GetParentClass(ObjCISA isa); 264 265 virtual TypeVendor * 266 GetTypeVendor() 267 { 268 return NULL; 269 } 270 271 // Finds the byte offset of the child_type ivar in parent_type. If it can't find the 272 // offset, returns LLDB_INVALID_IVAR_OFFSET. 273 274 virtual size_t 275 GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); 276 277 //------------------------------------------------------------------ 278 /// Chop up an objective C function prototype. 279 /// 280 /// Chop up an objective C function fullname and optionally fill in 281 /// any non-NULL ConstString objects. If a ConstString * is NULL, 282 /// then this name doesn't get filled in 283 /// 284 /// @param[in] name 285 /// A fully specified objective C function name. The string might 286 /// contain a category and it includes the leading "+" or "-" and 287 /// the square brackets, no types for the arguments, just the plain 288 /// selector. A few examples: 289 /// "-[NSStringDrawingContext init]" 290 /// "-[NSStringDrawingContext addString:inRect:]" 291 /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" 292 /// "+[NSString(NSStringDrawing) usesFontLeading]" 293 /// 294 /// @param[out] class_name 295 /// If non-NULL, this string will be filled in with the class 296 /// name including the category. The examples above would return: 297 /// "NSStringDrawingContext" 298 /// "NSStringDrawingContext" 299 /// "NSString(NSStringDrawing)" 300 /// "NSString(NSStringDrawing)" 301 /// 302 /// @param[out] selector_name 303 /// If non-NULL, this string will be filled in with the selector 304 /// name. The examples above would return: 305 /// "init" 306 /// "addString:inRect:" 307 /// "sizeWithAttributes:" 308 /// "usesFontLeading" 309 /// 310 /// @param[out] name_sans_category 311 /// If non-NULL, this string will be filled in with the class 312 /// name _without_ the category. If there is no category, and empty 313 /// string will be returned (as the result would be normally returned 314 /// in the "class_name" argument). The examples above would return: 315 /// <empty> 316 /// <empty> 317 /// "-[NSString sizeWithAttributes:]" 318 /// "+[NSString usesFontLeading]" 319 /// 320 /// @param[out] class_name_sans_category 321 /// If non-NULL, this string will be filled in with the prototype 322 /// name _without_ the category. If there is no category, and empty 323 /// string will be returned (as this is already the value that was 324 /// passed in). The examples above would return: 325 /// <empty> 326 /// <empty> 327 /// "NSString" 328 /// "NSString" 329 /// 330 /// @return 331 /// Returns the number of strings that were successfully filled 332 /// in. 333 //------------------------------------------------------------------ 334 static uint32_t 335 ParseMethodName (const char *name, 336 ConstString *class_name, // Class name (with category if there is one) 337 ConstString *selector_name, // selector only 338 ConstString *name_sans_category, // full function name with no category (empty if no category) 339 ConstString *class_name_sans_category);// Class name without category (empty if no category) 340 341 static bool 342 IsPossibleObjCMethodName (const char *name) 343 { 344 if (!name) 345 return false; 346 bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; 347 bool ends_right = (name[strlen(name) - 1] == ']'); 348 return (starts_right && ends_right); 349 } 350 351 static bool 352 IsPossibleObjCSelector (const char *name) 353 { 354 if (!name) 355 return false; 356 357 if (strchr(name, ':') == NULL) 358 return true; 359 else if (name[strlen(name) - 1] == ':') 360 return true; 361 else 362 return false; 363 } 364 365 bool 366 HasNewLiteralsAndIndexing () 367 { 368 if (m_has_new_literals_and_indexing == eLazyBoolCalculate) 369 { 370 if (CalculateHasNewLiteralsAndIndexing()) 371 m_has_new_literals_and_indexing = eLazyBoolYes; 372 else 373 m_has_new_literals_and_indexing = eLazyBoolNo; 374 } 375 376 return (m_has_new_literals_and_indexing == eLazyBoolYes); 377 } 378 379protected: 380 //------------------------------------------------------------------ 381 // Classes that inherit from ObjCLanguageRuntime can see and modify these 382 //------------------------------------------------------------------ 383 ObjCLanguageRuntime(Process *process); 384 385 virtual bool CalculateHasNewLiteralsAndIndexing() 386 { 387 return false; 388 } 389private: 390 // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver 391 // function over and over. 392 393 // FIXME: We need to watch for the loading of Protocols, and flush the cache for any 394 // class that we see so changed. 395 396 struct ClassAndSel 397 { 398 ClassAndSel() 399 { 400 sel_addr = LLDB_INVALID_ADDRESS; 401 class_addr = LLDB_INVALID_ADDRESS; 402 } 403 ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) : 404 class_addr (in_class_addr), 405 sel_addr(in_sel_addr) 406 { 407 } 408 bool operator== (const ClassAndSel &rhs) 409 { 410 if (class_addr == rhs.class_addr 411 && sel_addr == rhs.sel_addr) 412 return true; 413 else 414 return false; 415 } 416 417 bool operator< (const ClassAndSel &rhs) const 418 { 419 if (class_addr < rhs.class_addr) 420 return true; 421 else if (class_addr > rhs.class_addr) 422 return false; 423 else 424 { 425 if (sel_addr < rhs.sel_addr) 426 return true; 427 else 428 return false; 429 } 430 } 431 432 lldb::addr_t class_addr; 433 lldb::addr_t sel_addr; 434 }; 435 436 typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap; 437 MsgImplMap m_impl_cache; 438 439 LazyBool m_has_new_literals_and_indexing; 440protected: 441 typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; 442 typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; 443 ISAToDescriptorMap m_isa_to_descriptor_cache; 444 bool m_isa_to_descriptor_cache_is_up_to_date; 445 446 typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap; 447 typedef ClassNameMap::iterator ClassNameIterator; 448 ClassNameMap m_class_name_cache; 449 450 typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; 451 CompleteClassMap m_complete_class_cache; 452 453 DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); 454}; 455 456} // namespace lldb_private 457 458#endif // liblldb_ObjCLanguageRuntime_h_ 459