Home | History | Annotate | Download | only in DataFormatters
      1 //===-- FormatNavigator.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 lldb_FormatNavigator_h_
     11 #define lldb_FormatNavigator_h_
     12 
     13 // C Includes
     14 // C++ Includes
     15 
     16 // Other libraries and framework includes
     17 #include "clang/AST/DeclCXX.h"
     18 #include "clang/AST/Type.h"
     19 #include "clang/AST/DeclObjC.h"
     20 
     21 // Project includes
     22 #include "lldb/lldb-public.h"
     23 
     24 #include "lldb/Core/Log.h"
     25 #include "lldb/Core/RegularExpression.h"
     26 #include "lldb/Core/ValueObject.h"
     27 
     28 #include "lldb/DataFormatters/FormatClasses.h"
     29 
     30 #include "lldb/Symbol/ClangASTContext.h"
     31 #include "lldb/Symbol/ClangASTType.h"
     32 
     33 #include "lldb/Target/ObjCLanguageRuntime.h"
     34 #include "lldb/Target/Process.h"
     35 #include "lldb/Target/StackFrame.h"
     36 #include "lldb/Target/TargetList.h"
     37 
     38 namespace lldb_private {
     39 
     40 // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
     41 // class DataVisualization is the high-level front-end of this feature
     42 // clients should refer to that class as the entry-point into the data formatters
     43 // unless they have a good reason to bypass it and prefer to use this file's objects directly
     44 class IFormatChangeListener
     45 {
     46 public:
     47     virtual void
     48     Changed () = 0;
     49 
     50     virtual
     51     ~IFormatChangeListener () {}
     52 
     53     virtual uint32_t
     54     GetCurrentRevision () = 0;
     55 
     56 };
     57 
     58 static inline bool
     59 IsWhitespace (char c)
     60 {
     61     return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') );
     62 }
     63 
     64 static inline bool
     65 HasPrefix (const char* str1, const char* str2)
     66 {
     67     return ( ::strstr(str1, str2) == str1 );
     68 }
     69 
     70 // if the user tries to add formatters for, say, "struct Foo"
     71 // those will not match any type because of the way we strip qualifiers from typenames
     72 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
     73 // and strips the unnecessary qualifier
     74 static inline ConstString
     75 GetValidTypeName_Impl (const ConstString& type)
     76 {
     77     int strip_len = 0;
     78 
     79     if (type == false)
     80         return type;
     81 
     82     const char* type_cstr = type.AsCString();
     83 
     84     if ( HasPrefix(type_cstr, "class ") )
     85         strip_len = 6;
     86     else if ( HasPrefix(type_cstr, "enum ") )
     87         strip_len = 5;
     88     else if ( HasPrefix(type_cstr, "struct ") )
     89         strip_len = 7;
     90     else if ( HasPrefix(type_cstr, "union ") )
     91         strip_len = 6;
     92 
     93     if (strip_len == 0)
     94         return type;
     95 
     96     type_cstr += strip_len;
     97     while (IsWhitespace(*type_cstr) && ++type_cstr)
     98         ;
     99 
    100     return ConstString(type_cstr);
    101 }
    102 
    103 template<typename KeyType, typename ValueType>
    104 class FormatNavigator;
    105 
    106 template<typename KeyType, typename ValueType>
    107 class FormatMap
    108 {
    109 public:
    110 
    111     typedef typename ValueType::SharedPointer ValueSP;
    112     typedef std::map<KeyType, ValueSP> MapType;
    113     typedef typename MapType::iterator MapIterator;
    114     typedef bool(*CallbackType)(void*, KeyType, const ValueSP&);
    115 
    116     FormatMap(IFormatChangeListener* lst) :
    117     m_map(),
    118     m_map_mutex(Mutex::eMutexTypeRecursive),
    119     listener(lst)
    120     {
    121     }
    122 
    123     void
    124     Add(KeyType name,
    125         const ValueSP& entry)
    126     {
    127         if (listener)
    128             entry->GetRevision() = listener->GetCurrentRevision();
    129         else
    130             entry->GetRevision() = 0;
    131 
    132         Mutex::Locker locker(m_map_mutex);
    133         m_map[name] = entry;
    134         if (listener)
    135             listener->Changed();
    136     }
    137 
    138     bool
    139     Delete (KeyType name)
    140     {
    141         Mutex::Locker locker(m_map_mutex);
    142         MapIterator iter = m_map.find(name);
    143         if (iter == m_map.end())
    144             return false;
    145         m_map.erase(name);
    146         if (listener)
    147             listener->Changed();
    148         return true;
    149     }
    150 
    151     void
    152     Clear ()
    153     {
    154         Mutex::Locker locker(m_map_mutex);
    155         m_map.clear();
    156         if (listener)
    157             listener->Changed();
    158     }
    159 
    160     bool
    161     Get(KeyType name,
    162         ValueSP& entry)
    163     {
    164         Mutex::Locker locker(m_map_mutex);
    165         MapIterator iter = m_map.find(name);
    166         if (iter == m_map.end())
    167             return false;
    168         entry = iter->second;
    169         return true;
    170     }
    171 
    172     void
    173     LoopThrough (CallbackType callback, void* param)
    174     {
    175         if (callback)
    176         {
    177             Mutex::Locker locker(m_map_mutex);
    178             MapIterator pos, end = m_map.end();
    179             for (pos = m_map.begin(); pos != end; pos++)
    180             {
    181                 KeyType type = pos->first;
    182                 if (!callback(param, type, pos->second))
    183                     break;
    184             }
    185         }
    186     }
    187 
    188     uint32_t
    189     GetCount ()
    190     {
    191         return m_map.size();
    192     }
    193 
    194     ValueSP
    195     GetValueAtIndex (size_t index)
    196     {
    197         Mutex::Locker locker(m_map_mutex);
    198         MapIterator iter = m_map.begin();
    199         MapIterator end = m_map.end();
    200         while (index > 0)
    201         {
    202             iter++;
    203             index--;
    204             if (end == iter)
    205                 return ValueSP();
    206         }
    207         return iter->second;
    208     }
    209 
    210     KeyType
    211     GetKeyAtIndex (size_t index)
    212     {
    213         Mutex::Locker locker(m_map_mutex);
    214         MapIterator iter = m_map.begin();
    215         MapIterator end = m_map.end();
    216         while (index > 0)
    217         {
    218             iter++;
    219             index--;
    220             if (end == iter)
    221                 return KeyType();
    222         }
    223         return iter->first;
    224     }
    225 
    226 protected:
    227     MapType m_map;
    228     Mutex m_map_mutex;
    229     IFormatChangeListener* listener;
    230 
    231     MapType&
    232     map ()
    233     {
    234         return m_map;
    235     }
    236 
    237     Mutex&
    238     mutex ()
    239     {
    240         return m_map_mutex;
    241     }
    242 
    243     friend class FormatNavigator<KeyType, ValueType>;
    244     friend class FormatManager;
    245 
    246 };
    247 
    248 template<typename KeyType, typename ValueType>
    249 class FormatNavigator
    250 {
    251 protected:
    252     typedef FormatMap<KeyType,ValueType> BackEndType;
    253 
    254 public:
    255     typedef typename BackEndType::MapType MapType;
    256     typedef typename MapType::iterator MapIterator;
    257     typedef typename MapType::key_type MapKeyType;
    258     typedef typename MapType::mapped_type MapValueType;
    259     typedef typename BackEndType::CallbackType CallbackType;
    260     typedef typename std::shared_ptr<FormatNavigator<KeyType, ValueType> > SharedPointer;
    261 
    262     friend class TypeCategoryImpl;
    263 
    264     FormatNavigator(std::string name,
    265                     IFormatChangeListener* lst) :
    266     m_format_map(lst),
    267     m_name(name),
    268     m_id_cs(ConstString("id"))
    269     {
    270     }
    271 
    272     void
    273     Add (const MapKeyType &type, const MapValueType& entry)
    274     {
    275         Add_Impl(type, entry, (KeyType*)NULL);
    276     }
    277 
    278     bool
    279     Delete (ConstString type)
    280     {
    281         return Delete_Impl(type, (KeyType*)NULL);
    282     }
    283 
    284     bool
    285     Get(ValueObject& valobj,
    286         MapValueType& entry,
    287         lldb::DynamicValueType use_dynamic,
    288         uint32_t* why = NULL)
    289     {
    290         uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
    291         ClangASTType ast_type(valobj.GetClangType());
    292         bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
    293         if (ret)
    294             entry = MapValueType(entry);
    295         else
    296             entry = MapValueType();
    297         if (why)
    298             *why = value;
    299         return ret;
    300     }
    301 
    302     bool
    303     Get (ConstString type, MapValueType& entry)
    304     {
    305         return Get_Impl(type, entry, (KeyType*)NULL);
    306     }
    307 
    308     bool
    309     GetExact (ConstString type, MapValueType& entry)
    310     {
    311         return GetExact_Impl(type, entry, (KeyType*)NULL);
    312     }
    313 
    314     MapValueType
    315     GetAtIndex (size_t index)
    316     {
    317         return m_format_map.GetValueAtIndex(index);
    318     }
    319 
    320     lldb::TypeNameSpecifierImplSP
    321     GetTypeNameSpecifierAtIndex (size_t index)
    322     {
    323         return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL);
    324     }
    325 
    326     void
    327     Clear ()
    328     {
    329         m_format_map.Clear();
    330     }
    331 
    332     void
    333     LoopThrough (CallbackType callback, void* param)
    334     {
    335         m_format_map.LoopThrough(callback,param);
    336     }
    337 
    338     uint32_t
    339     GetCount ()
    340     {
    341         return m_format_map.GetCount();
    342     }
    343 
    344 protected:
    345 
    346     BackEndType m_format_map;
    347 
    348     std::string m_name;
    349 
    350     DISALLOW_COPY_AND_ASSIGN(FormatNavigator);
    351 
    352     ConstString m_id_cs;
    353 
    354     void
    355     Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
    356     {
    357        m_format_map.Add(type,entry);
    358     }
    359 
    360     void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
    361     {
    362        m_format_map.Add(GetValidTypeName_Impl(type), entry);
    363     }
    364 
    365     bool
    366     Delete_Impl (ConstString type, ConstString *dummy)
    367     {
    368        return m_format_map.Delete(type);
    369     }
    370 
    371     bool
    372     Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
    373     {
    374        Mutex& x_mutex = m_format_map.mutex();
    375         lldb_private::Mutex::Locker locker(x_mutex);
    376        MapIterator pos, end = m_format_map.map().end();
    377        for (pos = m_format_map.map().begin(); pos != end; pos++)
    378        {
    379            lldb::RegularExpressionSP regex = pos->first;
    380            if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
    381            {
    382                m_format_map.map().erase(pos);
    383                if (m_format_map.listener)
    384                    m_format_map.listener->Changed();
    385                return true;
    386            }
    387        }
    388        return false;
    389     }
    390 
    391     bool
    392     Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
    393     {
    394        return m_format_map.Get(type, entry);
    395     }
    396 
    397     bool
    398     GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
    399     {
    400         return Get_Impl(type,entry, (KeyType*)0);
    401     }
    402 
    403     lldb::TypeNameSpecifierImplSP
    404     GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
    405     {
    406         ConstString key = m_format_map.GetKeyAtIndex(index);
    407         if (key)
    408             return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
    409                                                                            false));
    410         else
    411             return lldb::TypeNameSpecifierImplSP();
    412     }
    413 
    414     lldb::TypeNameSpecifierImplSP
    415     GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
    416     {
    417         lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
    418         if (regex.get() == NULL)
    419             return lldb::TypeNameSpecifierImplSP();
    420         return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
    421                                                                        true));
    422     }
    423 
    424     bool
    425     Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
    426     {
    427        const char* key_cstr = key.AsCString();
    428        if (!key_cstr)
    429            return false;
    430        Mutex& x_mutex = m_format_map.mutex();
    431        lldb_private::Mutex::Locker locker(x_mutex);
    432        MapIterator pos, end = m_format_map.map().end();
    433        for (pos = m_format_map.map().begin(); pos != end; pos++)
    434        {
    435            lldb::RegularExpressionSP regex = pos->first;
    436            if (regex->Execute(key_cstr))
    437            {
    438                value = pos->second;
    439                return true;
    440            }
    441        }
    442        return false;
    443     }
    444 
    445     bool
    446     GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
    447     {
    448         Mutex& x_mutex = m_format_map.mutex();
    449         lldb_private::Mutex::Locker locker(x_mutex);
    450         MapIterator pos, end = m_format_map.map().end();
    451         for (pos = m_format_map.map().begin(); pos != end; pos++)
    452         {
    453             lldb::RegularExpressionSP regex = pos->first;
    454             if (strcmp(regex->GetText(),key.AsCString()) == 0)
    455             {
    456                 value = pos->second;
    457                 return true;
    458             }
    459         }
    460         return false;
    461     }
    462 
    463     bool
    464     Get_BitfieldMatch (ValueObject& valobj,
    465                        ConstString typeName,
    466                        MapValueType& entry,
    467                        uint32_t& reason)
    468     {
    469         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
    470         // for bitfields, append size to the typename so one can custom format them
    471         StreamString sstring;
    472         sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize());
    473         ConstString bitfieldname = ConstString(sstring.GetData());
    474         if (log)
    475             log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString());
    476         if (Get(bitfieldname, entry))
    477         {
    478             if (log)
    479                 log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning");
    480             return true;
    481         }
    482         else
    483         {
    484             reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
    485             if (log)
    486                 log->Printf("[Get_BitfieldMatch] no bitfield direct match");
    487             return false;
    488         }
    489     }
    490 
    491     bool Get_ObjC (ValueObject& valobj,
    492                    MapValueType& entry)
    493     {
    494         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
    495         lldb::ProcessSP process_sp = valobj.GetProcessSP();
    496         ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
    497         if (runtime == NULL)
    498         {
    499             if (log)
    500                 log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic");
    501             return false;
    502         }
    503         ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
    504         if (!objc_class_sp)
    505         {
    506             if (log)
    507                 log->Printf("[Get_ObjC] invalid ISA, skipping dynamic");
    508             return false;
    509         }
    510         ConstString name (objc_class_sp->GetClassName());
    511         if (log)
    512             log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
    513         if (Get(name, entry))
    514         {
    515             if (log)
    516                 log->Printf("[Get_ObjC] direct dynamic match found, returning");
    517             return true;
    518         }
    519         if (log)
    520             log->Printf("[Get_ObjC] no dynamic match");
    521         return false;
    522     }
    523 
    524     bool
    525     Get_Impl (ValueObject& valobj,
    526               ClangASTType clang_type,
    527               MapValueType& entry,
    528               lldb::DynamicValueType use_dynamic,
    529               uint32_t& reason)
    530     {
    531         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
    532 
    533         if (!clang_type.IsValid())
    534         {
    535             if (log)
    536                 log->Printf("[Get_Impl] type is invalid, returning");
    537             return false;
    538         }
    539 
    540         clang_type = clang_type.RemoveFastQualifiers();
    541 
    542         ConstString typeName(clang_type.GetConstTypeName());
    543 
    544         if (valobj.GetBitfieldBitSize() > 0)
    545         {
    546             if (Get_BitfieldMatch(valobj, typeName, entry, reason))
    547                 return true;
    548         }
    549 
    550         if (log)
    551             log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s",
    552                         m_name.c_str(),
    553                         valobj.GetName().AsCString(),
    554                         typeName.AsCString());
    555 
    556         if (Get(typeName, entry))
    557         {
    558             if (log)
    559                 log->Printf("[Get] direct match found, returning");
    560             return true;
    561         }
    562         if (log)
    563             log->Printf("[Get_Impl] no direct match");
    564 
    565         // strip pointers and references and see if that helps
    566         if (clang_type.IsReferenceType())
    567         {
    568             if (log)
    569                 log->Printf("[Get_Impl] stripping reference");
    570             if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences())
    571             {
    572                 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
    573                 return true;
    574             }
    575         }
    576         else if (clang_type.IsPointerType())
    577         {
    578             if (log)
    579                 log->Printf("[Get_Impl] stripping pointer");
    580             if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
    581             {
    582                 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
    583                 return true;
    584             }
    585         }
    586 
    587         bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL,
    588                                                                              false, // no C++
    589                                                                              true); // yes ObjC
    590 
    591         if (canBeObjCDynamic)
    592         {
    593             if (use_dynamic != lldb::eNoDynamicValues)
    594             {
    595                 if (log)
    596                     log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type");
    597                 if (Get_ObjC(valobj,entry))
    598                 {
    599                     reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery;
    600                     return true;
    601                 }
    602             }
    603             if (log)
    604                 log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer");
    605             if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
    606             {
    607                 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
    608                 return true;
    609             }
    610         }
    611 
    612         // try to strip typedef chains
    613         if (clang_type.IsTypedefType())
    614         {
    615             if (log)
    616                 log->Printf("[Get_Impl] stripping typedef");
    617             if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades())
    618             {
    619                 reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs;
    620                 return true;
    621             }
    622         }
    623 
    624         // out of luck here
    625         return false;
    626     }
    627 
    628     // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size)
    629     // but the type can change (e.g. stripping pointers, ...)
    630     bool Get (ValueObject& valobj,
    631               ClangASTType clang_type,
    632               MapValueType& entry,
    633               lldb::DynamicValueType use_dynamic,
    634               uint32_t& reason)
    635     {
    636         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
    637 
    638         if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason))
    639             return true;
    640 
    641         // try going to the unqualified type
    642         do {
    643             if (log)
    644                 log->Printf("[Get] trying the unqualified type");
    645             if (!clang_type.IsValid())
    646                 break;
    647 
    648             ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
    649             if (!unqual_clang_ast_type.IsValid())
    650             {
    651                 if (log)
    652                     log->Printf("[Get] could not get the unqual_clang_ast_type");
    653                 break;
    654             }
    655             if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
    656             {
    657                 if (log)
    658                     log->Printf("[Get] unqualified type is there and is not the same, let's try");
    659                 if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason))
    660                     return true;
    661             }
    662             else if (log)
    663                 log->Printf("[Get] unqualified type same as original type");
    664         } while(false);
    665 
    666         // if all else fails, go to static type
    667         if (valobj.IsDynamic())
    668         {
    669             if (log)
    670                 log->Printf("[Get] going to static value");
    671             lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
    672             if (static_value_sp)
    673             {
    674                 if (log)
    675                     log->Printf("[Get] has a static value - actually use it");
    676                 if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason))
    677                 {
    678                     reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue;
    679                     return true;
    680                 }
    681             }
    682         }
    683 
    684         return false;
    685     }
    686 };
    687 
    688 } // namespace lldb_private
    689 
    690 #endif	// lldb_FormatNavigator_h_
    691