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