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