ObjCLanguageRuntime.h revision 65529e3a02d91c25a779d8bac0c5bcd97c503ebd
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 virtual ClassDescriptorSP 178 GetClassDescriptor (ObjCISA isa); 179 180 ClassDescriptorSP 181 GetNonKVOClassDescriptor (ObjCISA isa); 182 183 virtual 184 ~ObjCLanguageRuntime(); 185 186 virtual lldb::LanguageType 187 GetLanguageType () const 188 { 189 return lldb::eLanguageTypeObjC; 190 } 191 192 virtual bool 193 IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 194 195 virtual bool 196 ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0; 197 198 virtual bool 199 HasReadObjCLibrary () = 0; 200 201 virtual lldb::ThreadPlanSP 202 GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0; 203 204 virtual ClassDescriptorSP 205 CreateClassDescriptor (ObjCISA isa) = 0; 206 207 lldb::addr_t 208 LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel); 209 210 void 211 AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr); 212 213 TypeAndOrName 214 LookupInClassNameCache (lldb::addr_t class_addr); 215 216 void 217 AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp); 218 219 void 220 AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name); 221 222 lldb::TypeSP 223 LookupInCompleteClassCache (ConstString &name); 224 225 virtual ClangUtilityFunction * 226 CreateObjectChecker (const char *) = 0; 227 228 virtual ObjCRuntimeVersions 229 GetRuntimeVersion () 230 { 231 return eObjC_VersionUnknown; 232 } 233 234 virtual bool 235 IsValidISA(ObjCISA isa) = 0; 236 237 virtual ObjCISA 238 GetISA(ValueObject& valobj) = 0; 239 240 virtual void 241 UpdateISAToDescriptorMap_Impl() 242 { 243 // to be implemented by runtimes if they support doing this 244 } 245 246 void 247 UpdateISAToDescriptorMap() 248 { 249 if (m_isa_to_descriptor_cache_is_up_to_date) 250 return; 251 252 m_isa_to_descriptor_cache_is_up_to_date = true; 253 254 UpdateISAToDescriptorMap_Impl(); 255 } 256 257 virtual ObjCISA 258 GetISA(const ConstString &name); 259 260 virtual ConstString 261 GetActualTypeName(ObjCISA isa); 262 263 virtual ObjCISA 264 GetParentClass(ObjCISA isa); 265 266 virtual TypeVendor * 267 GetTypeVendor() 268 { 269 return NULL; 270 } 271 272 // Finds the byte offset of the child_type ivar in parent_type. If it can't find the 273 // offset, returns LLDB_INVALID_IVAR_OFFSET. 274 275 virtual size_t 276 GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); 277 278 //------------------------------------------------------------------ 279 /// Chop up an objective C function prototype. 280 /// 281 /// Chop up an objective C function fullname and optionally fill in 282 /// any non-NULL ConstString objects. If a ConstString * is NULL, 283 /// then this name doesn't get filled in 284 /// 285 /// @param[in] name 286 /// A fully specified objective C function name. The string might 287 /// contain a category and it includes the leading "+" or "-" and 288 /// the square brackets, no types for the arguments, just the plain 289 /// selector. A few examples: 290 /// "-[NSStringDrawingContext init]" 291 /// "-[NSStringDrawingContext addString:inRect:]" 292 /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" 293 /// "+[NSString(NSStringDrawing) usesFontLeading]" 294 /// 295 /// @param[out] class_name 296 /// If non-NULL, this string will be filled in with the class 297 /// name including the category. The examples above would return: 298 /// "NSStringDrawingContext" 299 /// "NSStringDrawingContext" 300 /// "NSString(NSStringDrawing)" 301 /// "NSString(NSStringDrawing)" 302 /// 303 /// @param[out] selector_name 304 /// If non-NULL, this string will be filled in with the selector 305 /// name. The examples above would return: 306 /// "init" 307 /// "addString:inRect:" 308 /// "sizeWithAttributes:" 309 /// "usesFontLeading" 310 /// 311 /// @param[out] name_sans_category 312 /// If non-NULL, this string will be filled in with the class 313 /// name _without_ the category. If there is no category, and empty 314 /// string will be returned (as the result would be normally returned 315 /// in the "class_name" argument). The examples above would return: 316 /// <empty> 317 /// <empty> 318 /// "-[NSString sizeWithAttributes:]" 319 /// "+[NSString usesFontLeading]" 320 /// 321 /// @param[out] class_name_sans_category 322 /// If non-NULL, this string will be filled in with the prototype 323 /// name _without_ the category. If there is no category, and empty 324 /// string will be returned (as this is already the value that was 325 /// passed in). The examples above would return: 326 /// <empty> 327 /// <empty> 328 /// "NSString" 329 /// "NSString" 330 /// 331 /// @return 332 /// Returns the number of strings that were successfully filled 333 /// in. 334 //------------------------------------------------------------------ 335 static uint32_t 336 ParseMethodName (const char *name, 337 ConstString *class_name, // Class name (with category if there is one) 338 ConstString *selector_name, // selector only 339 ConstString *name_sans_category, // full function name with no category (empty if no category) 340 ConstString *class_name_sans_category);// Class name without category (empty if no category) 341 342 static bool 343 IsPossibleObjCMethodName (const char *name) 344 { 345 if (!name) 346 return false; 347 bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; 348 bool ends_right = (name[strlen(name) - 1] == ']'); 349 return (starts_right && ends_right); 350 } 351 352 static bool 353 IsPossibleObjCSelector (const char *name) 354 { 355 if (!name) 356 return false; 357 358 if (strchr(name, ':') == NULL) 359 return true; 360 else if (name[strlen(name) - 1] == ':') 361 return true; 362 else 363 return false; 364 } 365 366 bool 367 HasNewLiteralsAndIndexing () 368 { 369 if (m_has_new_literals_and_indexing == eLazyBoolCalculate) 370 { 371 if (CalculateHasNewLiteralsAndIndexing()) 372 m_has_new_literals_and_indexing = eLazyBoolYes; 373 else 374 m_has_new_literals_and_indexing = eLazyBoolNo; 375 } 376 377 return (m_has_new_literals_and_indexing == eLazyBoolYes); 378 } 379 380protected: 381 //------------------------------------------------------------------ 382 // Classes that inherit from ObjCLanguageRuntime can see and modify these 383 //------------------------------------------------------------------ 384 ObjCLanguageRuntime(Process *process); 385 386 virtual bool CalculateHasNewLiteralsAndIndexing() 387 { 388 return false; 389 } 390private: 391 // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver 392 // function over and over. 393 394 // FIXME: We need to watch for the loading of Protocols, and flush the cache for any 395 // class that we see so changed. 396 397 struct ClassAndSel 398 { 399 ClassAndSel() 400 { 401 sel_addr = LLDB_INVALID_ADDRESS; 402 class_addr = LLDB_INVALID_ADDRESS; 403 } 404 ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) : 405 class_addr (in_class_addr), 406 sel_addr(in_sel_addr) 407 { 408 } 409 bool operator== (const ClassAndSel &rhs) 410 { 411 if (class_addr == rhs.class_addr 412 && sel_addr == rhs.sel_addr) 413 return true; 414 else 415 return false; 416 } 417 418 bool operator< (const ClassAndSel &rhs) const 419 { 420 if (class_addr < rhs.class_addr) 421 return true; 422 else if (class_addr > rhs.class_addr) 423 return false; 424 else 425 { 426 if (sel_addr < rhs.sel_addr) 427 return true; 428 else 429 return false; 430 } 431 } 432 433 lldb::addr_t class_addr; 434 lldb::addr_t sel_addr; 435 }; 436 437 typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap; 438 MsgImplMap m_impl_cache; 439 440 LazyBool m_has_new_literals_and_indexing; 441protected: 442 typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; 443 typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; 444 ISAToDescriptorMap m_isa_to_descriptor_cache; 445 bool m_isa_to_descriptor_cache_is_up_to_date; 446 447 typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap; 448 typedef ClassNameMap::iterator ClassNameIterator; 449 ClassNameMap m_class_name_cache; 450 451 typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; 452 CompleteClassMap m_complete_class_cache; 453 454 DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); 455}; 456 457} // namespace lldb_private 458 459#endif // liblldb_ObjCLanguageRuntime_h_ 460