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