ObjCLanguageRuntime.h revision 81a5a09e76cfc1f110c0416e372f9f6cc27d79cf
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 <map>
16
17// Other libraries and framework includes
18// Project includes
19#include "lldb/lldb-private.h"
20#include "lldb/Core/PluginInterface.h"
21#include "lldb/Symbol/Type.h"
22#include "lldb/Symbol/TypeVendor.h"
23#include "lldb/Target/LanguageRuntime.h"
24
25namespace lldb_private {
26
27class ClangUtilityFunction;
28
29class ObjCLanguageRuntime :
30    public LanguageRuntime
31{
32public:
33
34    typedef lldb::addr_t ObjCISA;
35
36    class ClassDescriptor;
37    typedef STD_SHARED_PTR(ClassDescriptor) ClassDescriptorSP;
38
39    // the information that we want to support retrieving from an ObjC class
40    // this needs to be pure virtual since there are at least 2 different implementations
41    // of the runtime, and more might come
42    class ClassDescriptor
43    {
44    public:
45
46        ClassDescriptor() :
47        m_is_kvo(eLazyBoolCalculate),
48        m_is_cf(eLazyBoolCalculate)
49        {}
50
51        ClassDescriptor (ObjCISA isa, lldb::ProcessSP process)  :
52        m_is_kvo(eLazyBoolCalculate),
53        m_is_cf(eLazyBoolCalculate)
54        {}
55
56        virtual ConstString
57        GetClassName () = 0;
58
59        virtual ClassDescriptorSP
60        GetSuperclass () = 0;
61
62        // virtual if any implementation has some other version-specific rules
63        // but for the known v1/v2 this is all that needs to be done
64        virtual bool
65        IsKVO ()
66        {
67            if (m_is_kvo == eLazyBoolCalculate)
68            {
69                const char* class_name = GetClassName().AsCString();
70                m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name);
71            }
72            return (m_is_kvo == eLazyBoolYes);
73        }
74
75        // virtual if any implementation has some other version-specific rules
76        // but for the known v1/v2 this is all that needs to be done
77        virtual bool
78        IsCFType ()
79        {
80            if (m_is_cf == eLazyBoolCalculate)
81            {
82                const char* class_name = GetClassName().AsCString();
83                m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 ||
84                                     strcmp(class_name,"NSCFType") == 0);
85            }
86            return (m_is_cf == eLazyBoolYes);
87        }
88
89        virtual bool
90        IsValid () = 0;
91
92        virtual bool
93        IsTagged () = 0;
94
95        virtual uint64_t
96        GetInstanceSize () = 0;
97
98        virtual bool
99        IsRealized ()
100        {
101            // anything other than some instances of v2 classes are always realized
102            return true;
103        }
104
105        // use to implement version-specific additional constraints on pointers
106        virtual bool
107        CheckPointer (lldb::addr_t value,
108                      uint32_t ptr_size)
109        {
110            return true;
111        }
112
113        virtual ObjCISA
114        GetISA () = 0;
115
116        // This should return true iff the interface could be completed
117        virtual bool
118        CompleteInterface (clang::ObjCInterfaceDecl *interface_decl)
119        {
120            return false;
121        }
122
123        virtual
124        ~ClassDescriptor ()
125        {}
126
127    protected:
128        bool
129        IsPointerValid (lldb::addr_t value,
130                        uint32_t ptr_size,
131                        bool allow_NULLs = false,
132                        bool allow_tagged = false,
133                        bool check_version_specific = false);
134
135    private:
136        LazyBool m_is_kvo;
137        LazyBool m_is_cf;
138    };
139
140    // a convenience subclass of ClassDescriptor meant to represent invalid objects
141    class ClassDescriptor_Invalid : public ClassDescriptor
142    {
143    public:
144        ClassDescriptor_Invalid() {}
145
146        virtual ConstString
147        GetClassName () { return ConstString(""); }
148
149        virtual ClassDescriptorSP
150        GetSuperclass () { return ClassDescriptorSP(new ClassDescriptor_Invalid()); }
151
152        virtual bool
153        IsValid () { return false; }
154
155        virtual bool
156        IsTagged () { return false; }
157
158        virtual uint64_t
159        GetInstanceSize () { return 0; }
160
161        virtual ObjCISA
162        GetISA () { return 0; }
163
164        virtual bool
165        CheckPointer (lldb::addr_t value,
166                      uint32_t ptr_size) { return false; }
167
168        virtual
169        ~ClassDescriptor_Invalid ()
170        {}
171
172    };
173
174    virtual ClassDescriptorSP
175    GetClassDescriptor (ValueObject& in_value)
176    {
177        return ClassDescriptorSP();
178    }
179
180    virtual ClassDescriptorSP
181    GetClassDescriptor (ObjCISA isa)
182    {
183        return ClassDescriptorSP();
184    }
185
186    virtual
187    ~ObjCLanguageRuntime();
188
189    virtual lldb::LanguageType
190    GetLanguageType () const
191    {
192        return lldb::eLanguageTypeObjC;
193    }
194
195    virtual bool
196    IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
197
198    virtual bool
199    ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
200
201    virtual bool
202    HasReadObjCLibrary () = 0;
203
204    virtual lldb::ThreadPlanSP
205    GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 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