Home | History | Annotate | Download | only in Target
      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 
     27 namespace lldb_private {
     28 
     29 class ClangUtilityFunction;
     30 
     31 class ObjCLanguageRuntime :
     32     public LanguageRuntime
     33 {
     34 public:
     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 
    475 protected:
    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 
    519 private:
    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 
    577 protected:
    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