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