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