1//===-- TypeFormat.cpp ----------------------------------------*- 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#include "lldb/lldb-python.h"
11
12// C Includes
13
14// C++ Includes
15
16// Other libraries and framework includes
17
18// Project includes
19#include "lldb/lldb-public.h"
20#include "lldb/lldb-enumerations.h"
21
22#include "lldb/Core/Debugger.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Core/Timer.h"
25#include "lldb/DataFormatters/TypeFormat.h"
26#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Symbol/ClangASTType.h"
28#include "lldb/Symbol/TypeList.h"
29#include "lldb/Target/StackFrame.h"
30#include "lldb/Target/Target.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35TypeFormatImpl::TypeFormatImpl (const Flags& flags) :
36m_flags(flags),
37m_my_revision(0)
38{
39}
40
41
42TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
43                                              const TypeFormatImpl::Flags& flags) :
44TypeFormatImpl(flags),
45m_format (f)
46{
47}
48
49bool
50TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
51                                     std::string& dest) const
52{
53    if (!valobj)
54        return false;
55    if (valobj->GetClangType().IsAggregateType () == false)
56    {
57        const Value& value(valobj->GetValue());
58        const Value::ContextType context_type = value.GetContextType();
59        ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
60        DataExtractor data;
61
62        if (context_type == Value::eContextTypeRegisterInfo)
63        {
64            const RegisterInfo *reg_info = value.GetRegisterInfo();
65            if (reg_info)
66            {
67                valobj->GetData(data);
68
69                StreamString reg_sstr;
70                data.Dump (&reg_sstr,
71                           0,
72                           GetFormat(),
73                           reg_info->byte_size,
74                           1,
75                           UINT32_MAX,
76                           LLDB_INVALID_ADDRESS,
77                           0,
78                           0,
79                           exe_ctx.GetBestExecutionContextScope());
80                dest.swap(reg_sstr.GetString());
81            }
82        }
83        else
84        {
85            ClangASTType clang_type = valobj->GetClangType ();
86            if (clang_type)
87            {
88                // put custom bytes to display in the DataExtractor to override the default value logic
89                if (GetFormat() == eFormatCString)
90                {
91                    lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
92                    if (type_flags.Test(ClangASTType::eTypeIsPointer) && !type_flags.Test(ClangASTType::eTypeIsObjC))
93                    {
94                        // if we are dumping a pointer as a c-string, get the pointee data as a string
95                        TargetSP target_sp(valobj->GetTargetSP());
96                        if (target_sp)
97                        {
98                            size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
99                            Error error;
100                            DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0));
101                            Address address(valobj->GetPointerValue());
102                            if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success())
103                                data.SetData(buffer_sp);
104                        }
105                    }
106                }
107                else
108                    valobj->GetData(data);
109
110                StreamString sstr;
111                clang_type.DumpTypeValue (&sstr,                         // The stream to use for display
112                                          GetFormat(),                  // Format to display this type with
113                                          data,                         // Data to extract from
114                                          0,                             // Byte offset into "m_data"
115                                          valobj->GetByteSize(),                 // Byte size of item in "m_data"
116                                          valobj->GetBitfieldBitSize(),          // Bitfield bit size
117                                          valobj->GetBitfieldBitOffset(),        // Bitfield bit offset
118                                          exe_ctx.GetBestExecutionContextScope());
119                // Given that we do not want to set the ValueObject's m_error
120                // for a formatting error (or else we wouldn't be able to reformat
121                // until a next update), an empty string is treated as a "false"
122                // return from here, but that's about as severe as we get
123                // ClangASTType::DumpTypeValue() should always return
124                // something, even if that something is an error message
125                if (sstr.GetString().empty())
126                    dest.clear();
127                else
128                    dest.swap(sstr.GetString());
129            }
130        }
131        return !dest.empty();
132    }
133    else
134        return false;
135}
136
137std::string
138TypeFormatImpl_Format::GetDescription()
139{
140    StreamString sstr;
141    sstr.Printf ("%s%s%s%s",
142                 FormatManager::GetFormatAsCString (GetFormat()),
143                 Cascades() ? "" : " (not cascading)",
144                 SkipsPointers() ? " (skip pointers)" : "",
145                 SkipsReferences() ? " (skip references)" : "");
146    return sstr.GetString();
147}
148
149TypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name,
150                                                  const TypeFormatImpl::Flags& flags) :
151TypeFormatImpl(flags),
152m_enum_type(type_name),
153m_types()
154{
155}
156
157bool
158TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
159                                       std::string& dest) const
160{
161    dest.clear();
162    if (!valobj)
163        return false;
164    if (valobj->GetClangType().IsAggregateType ())
165        return false;
166    ProcessSP process_sp;
167    TargetSP target_sp;
168    void* valobj_key = (process_sp = valobj->GetProcessSP()).get();
169    if (!valobj_key)
170        valobj_key = (target_sp = valobj->GetTargetSP()).get();
171    else
172        target_sp = process_sp->GetTarget().shared_from_this();
173    if (!valobj_key)
174        return false;
175    auto iter = m_types.find(valobj_key),
176    end = m_types.end();
177    ClangASTType valobj_enum_type;
178    if (iter == end)
179    {
180        // probably a redundant check
181        if (!target_sp)
182            return false;
183        const ModuleList& images(target_sp->GetImages());
184        SymbolContext sc;
185        TypeList types;
186        images.FindTypes(sc, m_enum_type, false, UINT32_MAX, types);
187        if (types.GetSize() == 0)
188            return false;
189        for (lldb::TypeSP type_sp : types.Types())
190        {
191            if (!type_sp)
192                continue;
193            if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration)
194            {
195                valobj_enum_type = type_sp->GetClangFullType();
196                m_types.emplace(valobj_key,valobj_enum_type);
197                break;
198            }
199        }
200    }
201    else
202        valobj_enum_type = iter->second;
203    if (valobj_enum_type.IsValid() == false)
204        return false;
205    DataExtractor data;
206    valobj->GetData(data);
207    ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
208    StreamString sstr;
209    valobj_enum_type.DumpTypeValue(&sstr,
210                                   lldb::eFormatEnum,
211                                   data,
212                                   0,
213                                   data.GetByteSize(),
214                                   0,
215                                   0,
216                                   exe_ctx.GetBestExecutionContextScope());
217    if (!sstr.GetString().empty())
218        dest.swap(sstr.GetString());
219    return !dest.empty();
220}
221
222std::string
223TypeFormatImpl_EnumType::GetDescription()
224{
225    StreamString sstr;
226    sstr.Printf ("as type %s%s%s%s",
227                 m_enum_type.AsCString("<invalid type>"),
228                 Cascades() ? "" : " (not cascading)",
229                 SkipsPointers() ? " (skip pointers)" : "",
230                 SkipsReferences() ? " (skip references)" : "");
231    return sstr.GetString();
232}
233