ObjCLanguageRuntime.h revision 65529e3a02d91c25a779d8bac0c5bcd97c503ebd
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        // use to implement version-specific additional constraints on pointers
102        virtual bool
103        CheckPointer (lldb::addr_t value,
104                      uint32_t ptr_size) const
105        {
106            return true;
107        }
108
109        virtual ObjCISA
110        GetISA () = 0;
111
112        // This should return true iff the interface could be completed
113        virtual bool
114        Describe (std::function <void (ObjCISA)> const &superclass_func,
115                  std::function <void (const char*, const char*)> const &instance_method_func,
116                  std::function <void (const char*, const char*)> const &class_method_func)
117        {
118            return false;
119        }
120
121        virtual
122        ~ClassDescriptor ()
123        {}
124
125    protected:
126        bool
127        IsPointerValid (lldb::addr_t value,
128                        uint32_t ptr_size,
129                        bool allow_NULLs = false,
130                        bool allow_tagged = false,
131                        bool check_version_specific = false) const;
132
133    private:
134        LazyBool m_is_kvo;
135        LazyBool m_is_cf;
136    };
137
138    // a convenience subclass of ClassDescriptor meant to represent invalid objects
139    class ClassDescriptor_Invalid : public ClassDescriptor
140    {
141    public:
142        ClassDescriptor_Invalid() {}
143
144        virtual ConstString
145        GetClassName () { return ConstString(""); }
146
147        virtual ClassDescriptorSP
148        GetSuperclass () { return ClassDescriptorSP(new ClassDescriptor_Invalid()); }
149
150        virtual bool
151        IsValid () { return false; }
152
153        virtual bool
154        IsTagged () { return false; }
155
156        virtual uint64_t
157        GetInstanceSize () { return 0; }
158
159        virtual ObjCISA
160        GetISA () { return 0; }
161
162        virtual bool
163        CheckPointer (lldb::addr_t value, uint32_t ptr_size) const
164        {
165            return false;
166        }
167
168        virtual
169        ~ClassDescriptor_Invalid ()
170        {}
171
172    };
173
174    virtual ClassDescriptorSP
175    GetClassDescriptor (ValueObject& in_value);
176
177    virtual ClassDescriptorSP
178    GetClassDescriptor (ObjCISA isa);
179
180    ClassDescriptorSP
181    GetNonKVOClassDescriptor (ObjCISA isa);
182
183    virtual
184    ~ObjCLanguageRuntime();
185
186    virtual lldb::LanguageType
187    GetLanguageType () const
188    {
189        return lldb::eLanguageTypeObjC;
190    }
191
192    virtual bool
193    IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
194
195    virtual bool
196    ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
197
198    virtual bool
199    HasReadObjCLibrary () = 0;
200
201    virtual lldb::ThreadPlanSP
202    GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
203
204    virtual ClassDescriptorSP
205    CreateClassDescriptor (ObjCISA isa) = 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