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,
203                              uint64_t* payload = NULL) = 0;
204
205        virtual uint64_t
206        GetInstanceSize () = 0;
207
208        // use to implement version-specific additional constraints on pointers
209        virtual bool
210        CheckPointer (lldb::addr_t value,
211                      uint32_t ptr_size) const
212        {
213            return true;
214        }
215
216        virtual ObjCISA
217        GetISA () = 0;
218
219        // This should return true iff the interface could be completed
220        virtual bool
221        Describe (std::function <void (ObjCISA)> const &superclass_func,
222                  std::function <bool (const char*, const char*)> const &instance_method_func,
223                  std::function <bool (const char*, const char*)> const &class_method_func,
224                  std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
225        {
226            return false;
227        }
228
229        lldb::TypeSP
230        GetType ()
231        {
232            return m_type_wp.lock();
233        }
234
235        void
236        SetType (const lldb::TypeSP &type_sp)
237        {
238            m_type_wp = type_sp;
239        }
240
241    protected:
242        bool
243        IsPointerValid (lldb::addr_t value,
244                        uint32_t ptr_size,
245                        bool allow_NULLs = false,
246                        bool allow_tagged = false,
247                        bool check_version_specific = false) const;
248
249    private:
250        LazyBool m_is_kvo;
251        LazyBool m_is_cf;
252        lldb::TypeWP m_type_wp;
253    };
254
255    virtual ClassDescriptorSP
256    GetClassDescriptor (ValueObject& in_value);
257
258    ClassDescriptorSP
259    GetNonKVOClassDescriptor (ValueObject& in_value);
260
261    virtual ClassDescriptorSP
262    GetClassDescriptorFromClassName (const ConstString &class_name);
263
264    virtual ClassDescriptorSP
265    GetClassDescriptorFromISA (ObjCISA isa);
266
267    ClassDescriptorSP
268    GetNonKVOClassDescriptor (ObjCISA isa);
269
270    virtual
271    ~ObjCLanguageRuntime();
272
273    virtual lldb::LanguageType
274    GetLanguageType () const
275    {
276        return lldb::eLanguageTypeObjC;
277    }
278
279    virtual bool
280    IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
281
282    virtual bool
283    ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
284
285    virtual bool
286    HasReadObjCLibrary () = 0;
287
288    virtual lldb::ThreadPlanSP
289    GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
290
291    lldb::addr_t
292    LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
293
294    void
295    AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr);
296
297    TypeAndOrName
298    LookupInClassNameCache (lldb::addr_t class_addr);
299
300    void
301    AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp);
302
303    void
304    AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name);
305
306    lldb::TypeSP
307    LookupInCompleteClassCache (ConstString &name);
308
309    virtual ClangUtilityFunction *
310    CreateObjectChecker (const char *) = 0;
311
312    virtual ObjCRuntimeVersions
313    GetRuntimeVersion ()
314    {
315        return eObjC_VersionUnknown;
316    }
317
318    bool
319    IsValidISA(ObjCISA isa)
320    {
321        UpdateISAToDescriptorMap();
322        return m_isa_to_descriptor.count(isa) > 0;
323    }
324
325    virtual void
326    UpdateISAToDescriptorMapIfNeeded() = 0;
327
328    void
329    UpdateISAToDescriptorMap()
330    {
331        if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id)
332        {
333            UpdateISAToDescriptorMapIfNeeded ();
334        }
335    }
336
337    virtual ObjCISA
338    GetISA(const ConstString &name);
339
340    virtual ConstString
341    GetActualTypeName(ObjCISA isa);
342
343    virtual ObjCISA
344    GetParentClass(ObjCISA isa);
345
346    virtual TypeVendor *
347    GetTypeVendor()
348    {
349        return NULL;
350    }
351
352    // Finds the byte offset of the child_type ivar in parent_type.  If it can't find the
353    // offset, returns LLDB_INVALID_IVAR_OFFSET.
354
355    virtual size_t
356    GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
357
358    // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol),
359    // try to determine from the runtime what the value of that symbol would be.
360    // Useful when the underlying binary is stripped.
361    virtual lldb::addr_t
362    LookupRuntimeSymbol (const ConstString &name)
363    {
364        return LLDB_INVALID_ADDRESS;
365    }
366
367    //------------------------------------------------------------------
368    /// Chop up an objective C function prototype.
369    ///
370    /// Chop up an objective C function fullname and optionally fill in
371    /// any non-NULL ConstString objects. If a ConstString * is NULL,
372    /// then this name doesn't get filled in
373    ///
374    /// @param[in] name
375    ///     A fully specified objective C function name. The string might
376    ///     contain a category and it includes the leading "+" or "-" and
377    ///     the square brackets, no types for the arguments, just the plain
378    ///     selector. A few examples:
379    ///         "-[NSStringDrawingContext init]"
380    ///         "-[NSStringDrawingContext addString:inRect:]"
381    ///         "-[NSString(NSStringDrawing) sizeWithAttributes:]"
382    ///         "+[NSString(NSStringDrawing) usesFontLeading]"
383    ///
384    /// @param[out] class_name
385    ///     If non-NULL, this string will be filled in with the class
386    ///     name including the category. The examples above would return:
387    ///         "NSStringDrawingContext"
388    ///         "NSStringDrawingContext"
389    ///         "NSString(NSStringDrawing)"
390    ///         "NSString(NSStringDrawing)"
391    ///
392    /// @param[out] selector_name
393    ///     If non-NULL, this string will be filled in with the selector
394    ///     name. The examples above would return:
395    ///         "init"
396    ///         "addString:inRect:"
397    ///         "sizeWithAttributes:"
398    ///         "usesFontLeading"
399    ///
400    /// @param[out] name_sans_category
401    ///     If non-NULL, this string will be filled in with the class
402    ///     name _without_ the category. If there is no category, and empty
403    ///     string will be returned (as the result would be normally returned
404    ///     in the "class_name" argument). The examples above would return:
405    ///         <empty>
406    ///         <empty>
407    ///         "-[NSString sizeWithAttributes:]"
408    ///         "+[NSString usesFontLeading]"
409    ///
410    /// @param[out] class_name_sans_category
411    ///     If non-NULL, this string will be filled in with the prototype
412    ///     name _without_ the category. If there is no category, and empty
413    ///     string will be returned (as this is already the value that was
414    ///     passed in). The examples above would return:
415    ///         <empty>
416    ///         <empty>
417    ///         "NSString"
418    ///         "NSString"
419    ///
420    /// @return
421    ///     Returns the number of strings that were successfully filled
422    ///     in.
423    //------------------------------------------------------------------
424//    static uint32_t
425//    ParseMethodName (const char *name,
426//                     ConstString *class_name,               // Class name (with category if there is one)
427//                     ConstString *selector_name,            // selector only
428//                     ConstString *name_sans_category,       // full function name with no category (empty if no category)
429//                     ConstString *class_name_sans_category);// Class name without category (empty if no category)
430
431    static bool
432    IsPossibleObjCMethodName (const char *name)
433    {
434        if (!name)
435            return false;
436        bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
437        bool ends_right = (name[strlen(name) - 1] == ']');
438        return (starts_right && ends_right);
439    }
440
441    static bool
442    IsPossibleObjCSelector (const char *name)
443    {
444        if (!name)
445            return false;
446
447        if (strchr(name, ':') == NULL)
448            return true;
449        else if (name[strlen(name) - 1] == ':')
450            return true;
451        else
452            return false;
453    }
454
455    bool
456    HasNewLiteralsAndIndexing ()
457    {
458        if (m_has_new_literals_and_indexing == eLazyBoolCalculate)
459        {
460            if (CalculateHasNewLiteralsAndIndexing())
461                m_has_new_literals_and_indexing = eLazyBoolYes;
462            else
463                m_has_new_literals_and_indexing = eLazyBoolNo;
464        }
465
466        return (m_has_new_literals_and_indexing == eLazyBoolYes);
467    }
468
469    virtual void
470    SymbolsDidLoad (const ModuleList& module_list)
471    {
472        m_negative_complete_class_cache.clear();
473    }
474
475protected:
476    //------------------------------------------------------------------
477    // Classes that inherit from ObjCLanguageRuntime can see and modify these
478    //------------------------------------------------------------------
479    ObjCLanguageRuntime(Process *process);
480
481    virtual bool CalculateHasNewLiteralsAndIndexing()
482    {
483        return false;
484    }
485
486
487    bool
488    ISAIsCached (ObjCISA isa) const
489    {
490        return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end();
491    }
492
493    bool
494    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
495    {
496        if (isa != 0)
497        {
498            m_isa_to_descriptor[isa] = descriptor_sp;
499            return true;
500        }
501        return false;
502    }
503
504    bool
505    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name);
506
507    bool
508    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash)
509    {
510        if (isa != 0)
511        {
512            m_isa_to_descriptor[isa] = descriptor_sp;
513            m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa));
514            return true;
515        }
516        return false;
517    }
518
519private:
520    // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver
521    // function over and over.
522
523    // FIXME: We need to watch for the loading of Protocols, and flush the cache for any
524    // class that we see so changed.
525
526    struct ClassAndSel
527    {
528        ClassAndSel()
529        {
530            sel_addr = LLDB_INVALID_ADDRESS;
531            class_addr = LLDB_INVALID_ADDRESS;
532        }
533        ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) :
534            class_addr (in_class_addr),
535            sel_addr(in_sel_addr)
536        {
537        }
538        bool operator== (const ClassAndSel &rhs)
539        {
540            if (class_addr == rhs.class_addr
541                && sel_addr == rhs.sel_addr)
542                return true;
543            else
544                return false;
545        }
546
547        bool operator< (const ClassAndSel &rhs) const
548        {
549            if (class_addr < rhs.class_addr)
550                return true;
551            else if (class_addr > rhs.class_addr)
552                return false;
553            else
554            {
555                if (sel_addr < rhs.sel_addr)
556                    return true;
557                else
558                    return false;
559            }
560        }
561
562        lldb::addr_t class_addr;
563        lldb::addr_t sel_addr;
564    };
565
566    typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap;
567    typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap;
568    typedef std::multimap<uint32_t, ObjCISA> HashToISAMap;
569    typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator;
570    typedef HashToISAMap::iterator HashToISAIterator;
571
572    MsgImplMap m_impl_cache;
573    LazyBool m_has_new_literals_and_indexing;
574    ISAToDescriptorMap m_isa_to_descriptor;
575    HashToISAMap m_hash_to_isa_map;
576
577protected:
578    uint32_t m_isa_to_descriptor_stop_id;
579
580    typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
581    CompleteClassMap m_complete_class_cache;
582
583    struct ConstStringSetHelpers {
584        size_t operator () (const ConstString& arg) const // for hashing
585        {
586            return (size_t)arg.GetCString();
587        }
588        bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality
589        {
590            return arg1.operator==(arg2);
591        }
592    };
593    typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet;
594    CompleteClassSet m_negative_complete_class_cache;
595
596    ISAToDescriptorIterator
597    GetDescriptorIterator (const ConstString &name);
598
599    DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime);
600};
601
602} // namespace lldb_private
603
604#endif  // liblldb_ObjCLanguageRuntime_h_
605