1 //===-- ObjCLanguageRuntime.h ---------------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_ObjCLanguageRuntime_h_
11 #define liblldb_ObjCLanguageRuntime_h_
17 #include <unordered_set>
19 // Other libraries and framework 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"
27 namespace lldb_private {
29 class ClangUtilityFunction;
31 class ObjCLanguageRuntime :
32 public LanguageRuntime
50 m_type (eTypeUnspecified),
51 m_category_is_valid (false)
55 MethodName (const char *name, bool strict) :
60 m_type (eTypeUnspecified),
61 m_category_is_valid (false)
63 SetName (name, strict);
70 IsValid (bool strict) const
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)
76 // Other than that, m_full will only be filled in if the objective C
84 return (bool)GetCategory();
100 GetFullNameWithoutCategory (bool empty_if_no_category);
103 SetName (const char *name, bool strict);
109 GetClassNameWithCategory ();
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:]"
127 GetFullNames (std::vector<ConstString> &names, bool append);
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:"
135 bool m_category_is_valid;
138 typedef lldb::addr_t ObjCISA;
140 class ClassDescriptor;
141 typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP;
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
151 m_is_kvo (eLazyBoolCalculate),
152 m_is_cf (eLazyBoolCalculate),
165 virtual ClassDescriptorSP
166 GetSuperclass () = 0;
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
173 if (m_is_kvo == eLazyBoolCalculate)
175 const char* class_name = GetClassName().AsCString();
176 if (class_name && *class_name)
177 m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name);
179 return (m_is_kvo == eLazyBoolYes);
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
187 if (m_is_cf == eLazyBoolCalculate)
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);
194 return (m_is_cf == eLazyBoolYes);
201 GetTaggedPointerInfo (uint64_t* info_bits = NULL,
202 uint64_t* value_bits = NULL,
203 uint64_t* payload = NULL) = 0;
206 GetInstanceSize () = 0;
208 // use to implement version-specific additional constraints on pointers
210 CheckPointer (lldb::addr_t value,
211 uint32_t ptr_size) const
219 // This should return true iff the interface could be completed
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)
232 return m_type_wp.lock();
236 SetType (const lldb::TypeSP &type_sp)
243 IsPointerValid (lldb::addr_t value,
245 bool allow_NULLs = false,
246 bool allow_tagged = false,
247 bool check_version_specific = false) const;
252 lldb::TypeWP m_type_wp;
255 virtual ClassDescriptorSP
256 GetClassDescriptor (ValueObject& in_value);
259 GetNonKVOClassDescriptor (ValueObject& in_value);
261 virtual ClassDescriptorSP
262 GetClassDescriptorFromClassName (const ConstString &class_name);
264 virtual ClassDescriptorSP
265 GetClassDescriptorFromISA (ObjCISA isa);
268 GetNonKVOClassDescriptor (ObjCISA isa);
271 ~ObjCLanguageRuntime();
273 virtual lldb::LanguageType
274 GetLanguageType () const
276 return lldb::eLanguageTypeObjC;
280 IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
283 ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
286 HasReadObjCLibrary () = 0;
288 virtual lldb::ThreadPlanSP
289 GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
292 LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
295 AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr);
298 LookupInClassNameCache (lldb::addr_t class_addr);
301 AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp);
304 AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name);
307 LookupInCompleteClassCache (ConstString &name);
309 virtual ClangUtilityFunction *
310 CreateObjectChecker (const char *) = 0;
312 virtual ObjCRuntimeVersions
315 return eObjC_VersionUnknown;
319 IsValidISA(ObjCISA isa)
321 UpdateISAToDescriptorMap();
322 return m_isa_to_descriptor.count(isa) > 0;
326 UpdateISAToDescriptorMapIfNeeded() = 0;
329 UpdateISAToDescriptorMap()
331 if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id)
333 UpdateISAToDescriptorMapIfNeeded ();
338 GetISA(const ConstString &name);
341 GetActualTypeName(ObjCISA isa);
344 GetParentClass(ObjCISA isa);
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.
356 GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
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.
362 LookupRuntimeSymbol (const ConstString &name)
364 return LLDB_INVALID_ADDRESS;
367 //------------------------------------------------------------------
368 /// Chop up an objective C function prototype.
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
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]"
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)"
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:
396 /// "addString:inRect:"
397 /// "sizeWithAttributes:"
398 /// "usesFontLeading"
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:
407 /// "-[NSString sizeWithAttributes:]"
408 /// "+[NSString usesFontLeading]"
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:
421 /// Returns the number of strings that were successfully filled
423 //------------------------------------------------------------------
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)
432 IsPossibleObjCMethodName (const char *name)
436 bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
437 bool ends_right = (name[strlen(name) - 1] == ']');
438 return (starts_right && ends_right);
442 IsPossibleObjCSelector (const char *name)
447 if (strchr(name, ':') == NULL)
449 else if (name[strlen(name) - 1] == ':')
456 HasNewLiteralsAndIndexing ()
458 if (m_has_new_literals_and_indexing == eLazyBoolCalculate)
460 if (CalculateHasNewLiteralsAndIndexing())
461 m_has_new_literals_and_indexing = eLazyBoolYes;
463 m_has_new_literals_and_indexing = eLazyBoolNo;
466 return (m_has_new_literals_and_indexing == eLazyBoolYes);
470 SymbolsDidLoad (const ModuleList& module_list)
472 m_negative_complete_class_cache.clear();
476 //------------------------------------------------------------------
477 // Classes that inherit from ObjCLanguageRuntime can see and modify these
478 //------------------------------------------------------------------
479 ObjCLanguageRuntime(Process *process);
481 virtual bool CalculateHasNewLiteralsAndIndexing()
488 ISAIsCached (ObjCISA isa) const
490 return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end();
494 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
498 m_isa_to_descriptor[isa] = descriptor_sp;
505 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name);
508 AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash)
512 m_isa_to_descriptor[isa] = descriptor_sp;
513 m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa));
520 // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver
521 // function over and over.
523 // FIXME: We need to watch for the loading of Protocols, and flush the cache for any
524 // class that we see so changed.
530 sel_addr = LLDB_INVALID_ADDRESS;
531 class_addr = LLDB_INVALID_ADDRESS;
533 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)
538 bool operator== (const ClassAndSel &rhs)
540 if (class_addr == rhs.class_addr
541 && sel_addr == rhs.sel_addr)
547 bool operator< (const ClassAndSel &rhs) const
549 if (class_addr < rhs.class_addr)
551 else if (class_addr > rhs.class_addr)
555 if (sel_addr < rhs.sel_addr)
562 lldb::addr_t class_addr;
563 lldb::addr_t sel_addr;
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;
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;
578 uint32_t m_isa_to_descriptor_stop_id;
580 typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
581 CompleteClassMap m_complete_class_cache;
583 struct ConstStringSetHelpers {
584 size_t operator () (const ConstString& arg) const // for hashing
586 return (size_t)arg.GetCString();
588 bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality
590 return arg1.operator==(arg2);
593 typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet;
594 CompleteClassSet m_negative_complete_class_cache;
596 ISAToDescriptorIterator
597 GetDescriptorIterator (const ConstString &name);
599 DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime);
602 } // namespace lldb_private
604 #endif // liblldb_ObjCLanguageRuntime_h_