1254721Semaste//===-- TypeFormat.cpp ----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste
14254721Semaste// C++ Includes
15254721Semaste
16254721Semaste// Other libraries and framework includes
17254721Semaste
18254721Semaste// Project includes
19254721Semaste#include "lldb/lldb-public.h"
20254721Semaste#include "lldb/lldb-enumerations.h"
21254721Semaste
22254721Semaste#include "lldb/Core/Debugger.h"
23254721Semaste#include "lldb/Core/StreamString.h"
24254721Semaste#include "lldb/Core/Timer.h"
25254721Semaste#include "lldb/DataFormatters/TypeFormat.h"
26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
27254721Semaste#include "lldb/Symbol/ClangASTType.h"
28269024Semaste#include "lldb/Symbol/TypeList.h"
29254721Semaste#include "lldb/Target/StackFrame.h"
30254721Semaste#include "lldb/Target/Target.h"
31254721Semaste
32254721Semasteusing namespace lldb;
33254721Semasteusing namespace lldb_private;
34254721Semaste
35269024SemasteTypeFormatImpl::TypeFormatImpl (const Flags& flags) :
36254721Semastem_flags(flags),
37269024Semastem_my_revision(0)
38269024Semaste{
39269024Semaste}
40269024Semaste
41269024Semaste
42269024SemasteTypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
43269024Semaste                                              const TypeFormatImpl::Flags& flags) :
44269024SemasteTypeFormatImpl(flags),
45254721Semastem_format (f)
46254721Semaste{
47254721Semaste}
48254721Semaste
49269024Semastebool
50269024SemasteTypeFormatImpl_Format::FormatObject (ValueObject *valobj,
51269024Semaste                                     std::string& dest) const
52269024Semaste{
53269024Semaste    if (!valobj)
54269024Semaste        return false;
55269024Semaste    if (valobj->GetClangType().IsAggregateType () == false)
56269024Semaste    {
57269024Semaste        const Value& value(valobj->GetValue());
58269024Semaste        const Value::ContextType context_type = value.GetContextType();
59269024Semaste        ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
60269024Semaste        DataExtractor data;
61269024Semaste
62269024Semaste        if (context_type == Value::eContextTypeRegisterInfo)
63269024Semaste        {
64269024Semaste            const RegisterInfo *reg_info = value.GetRegisterInfo();
65269024Semaste            if (reg_info)
66269024Semaste            {
67269024Semaste                valobj->GetData(data);
68269024Semaste
69269024Semaste                StreamString reg_sstr;
70269024Semaste                data.Dump (&reg_sstr,
71269024Semaste                           0,
72269024Semaste                           GetFormat(),
73269024Semaste                           reg_info->byte_size,
74269024Semaste                           1,
75269024Semaste                           UINT32_MAX,
76269024Semaste                           LLDB_INVALID_ADDRESS,
77269024Semaste                           0,
78269024Semaste                           0,
79269024Semaste                           exe_ctx.GetBestExecutionContextScope());
80269024Semaste                dest.swap(reg_sstr.GetString());
81269024Semaste            }
82269024Semaste        }
83269024Semaste        else
84269024Semaste        {
85269024Semaste            ClangASTType clang_type = valobj->GetClangType ();
86269024Semaste            if (clang_type)
87269024Semaste            {
88269024Semaste                // put custom bytes to display in the DataExtractor to override the default value logic
89269024Semaste                if (GetFormat() == eFormatCString)
90269024Semaste                {
91269024Semaste                    lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
92269024Semaste                    if (type_flags.Test(ClangASTType::eTypeIsPointer) && !type_flags.Test(ClangASTType::eTypeIsObjC))
93269024Semaste                    {
94269024Semaste                        // if we are dumping a pointer as a c-string, get the pointee data as a string
95269024Semaste                        TargetSP target_sp(valobj->GetTargetSP());
96269024Semaste                        if (target_sp)
97269024Semaste                        {
98269024Semaste                            size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
99269024Semaste                            Error error;
100269024Semaste                            DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0));
101269024Semaste                            Address address(valobj->GetPointerValue());
102269024Semaste                            if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success())
103269024Semaste                                data.SetData(buffer_sp);
104269024Semaste                        }
105269024Semaste                    }
106269024Semaste                }
107269024Semaste                else
108269024Semaste                    valobj->GetData(data);
109269024Semaste
110269024Semaste                StreamString sstr;
111269024Semaste                clang_type.DumpTypeValue (&sstr,                         // The stream to use for display
112269024Semaste                                          GetFormat(),                  // Format to display this type with
113269024Semaste                                          data,                         // Data to extract from
114269024Semaste                                          0,                             // Byte offset into "m_data"
115269024Semaste                                          valobj->GetByteSize(),                 // Byte size of item in "m_data"
116269024Semaste                                          valobj->GetBitfieldBitSize(),          // Bitfield bit size
117269024Semaste                                          valobj->GetBitfieldBitOffset(),        // Bitfield bit offset
118269024Semaste                                          exe_ctx.GetBestExecutionContextScope());
119269024Semaste                // Given that we do not want to set the ValueObject's m_error
120269024Semaste                // for a formatting error (or else we wouldn't be able to reformat
121269024Semaste                // until a next update), an empty string is treated as a "false"
122269024Semaste                // return from here, but that's about as severe as we get
123269024Semaste                // ClangASTType::DumpTypeValue() should always return
124269024Semaste                // something, even if that something is an error message
125269024Semaste                if (sstr.GetString().empty())
126269024Semaste                    dest.clear();
127269024Semaste                else
128269024Semaste                    dest.swap(sstr.GetString());
129269024Semaste            }
130269024Semaste        }
131269024Semaste        return !dest.empty();
132269024Semaste    }
133269024Semaste    else
134269024Semaste        return false;
135269024Semaste}
136269024Semaste
137254721Semastestd::string
138269024SemasteTypeFormatImpl_Format::GetDescription()
139254721Semaste{
140254721Semaste    StreamString sstr;
141263363Semaste    sstr.Printf ("%s%s%s%s",
142254721Semaste                 FormatManager::GetFormatAsCString (GetFormat()),
143254721Semaste                 Cascades() ? "" : " (not cascading)",
144254721Semaste                 SkipsPointers() ? " (skip pointers)" : "",
145254721Semaste                 SkipsReferences() ? " (skip references)" : "");
146254721Semaste    return sstr.GetString();
147254721Semaste}
148254721Semaste
149269024SemasteTypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name,
150269024Semaste                                                  const TypeFormatImpl::Flags& flags) :
151269024SemasteTypeFormatImpl(flags),
152269024Semastem_enum_type(type_name),
153269024Semastem_types()
154269024Semaste{
155269024Semaste}
156269024Semaste
157269024Semastebool
158269024SemasteTypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
159269024Semaste                                       std::string& dest) const
160269024Semaste{
161269024Semaste    dest.clear();
162269024Semaste    if (!valobj)
163269024Semaste        return false;
164269024Semaste    if (valobj->GetClangType().IsAggregateType ())
165269024Semaste        return false;
166269024Semaste    ProcessSP process_sp;
167269024Semaste    TargetSP target_sp;
168269024Semaste    void* valobj_key = (process_sp = valobj->GetProcessSP()).get();
169269024Semaste    if (!valobj_key)
170269024Semaste        valobj_key = (target_sp = valobj->GetTargetSP()).get();
171269024Semaste    else
172269024Semaste        target_sp = process_sp->GetTarget().shared_from_this();
173269024Semaste    if (!valobj_key)
174269024Semaste        return false;
175269024Semaste    auto iter = m_types.find(valobj_key),
176269024Semaste    end = m_types.end();
177269024Semaste    ClangASTType valobj_enum_type;
178269024Semaste    if (iter == end)
179269024Semaste    {
180269024Semaste        // probably a redundant check
181269024Semaste        if (!target_sp)
182269024Semaste            return false;
183269024Semaste        const ModuleList& images(target_sp->GetImages());
184269024Semaste        SymbolContext sc;
185269024Semaste        TypeList types;
186269024Semaste        images.FindTypes(sc, m_enum_type, false, UINT32_MAX, types);
187269024Semaste        if (types.GetSize() == 0)
188269024Semaste            return false;
189269024Semaste        for (lldb::TypeSP type_sp : types.Types())
190269024Semaste        {
191269024Semaste            if (!type_sp)
192269024Semaste                continue;
193269024Semaste            if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration)
194269024Semaste            {
195269024Semaste                valobj_enum_type = type_sp->GetClangFullType();
196269024Semaste                m_types.emplace(valobj_key,valobj_enum_type);
197269024Semaste                break;
198269024Semaste            }
199269024Semaste        }
200269024Semaste    }
201269024Semaste    else
202269024Semaste        valobj_enum_type = iter->second;
203269024Semaste    if (valobj_enum_type.IsValid() == false)
204269024Semaste        return false;
205269024Semaste    DataExtractor data;
206269024Semaste    valobj->GetData(data);
207269024Semaste    ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
208269024Semaste    StreamString sstr;
209269024Semaste    valobj_enum_type.DumpTypeValue(&sstr,
210269024Semaste                                   lldb::eFormatEnum,
211269024Semaste                                   data,
212269024Semaste                                   0,
213269024Semaste                                   data.GetByteSize(),
214269024Semaste                                   0,
215269024Semaste                                   0,
216269024Semaste                                   exe_ctx.GetBestExecutionContextScope());
217269024Semaste    if (!sstr.GetString().empty())
218269024Semaste        dest.swap(sstr.GetString());
219269024Semaste    return !dest.empty();
220269024Semaste}
221269024Semaste
222269024Semastestd::string
223269024SemasteTypeFormatImpl_EnumType::GetDescription()
224269024Semaste{
225269024Semaste    StreamString sstr;
226269024Semaste    sstr.Printf ("as type %s%s%s%s",
227269024Semaste                 m_enum_type.AsCString("<invalid type>"),
228269024Semaste                 Cascades() ? "" : " (not cascading)",
229269024Semaste                 SkipsPointers() ? " (skip pointers)" : "",
230269024Semaste                 SkipsReferences() ? " (skip references)" : "");
231269024Semaste    return sstr.GetString();
232269024Semaste}
233