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