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