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
32 using namespace lldb;
33 using namespace lldb_private;
34
TypeFormatImpl(const Flags & flags)35 TypeFormatImpl::TypeFormatImpl (const Flags& flags) :
36 m_flags(flags),
37 m_my_revision(0)
38 {
39 }
40
41
TypeFormatImpl_Format(lldb::Format f,const TypeFormatImpl::Flags & flags)42 TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
43 const TypeFormatImpl::Flags& flags) :
44 TypeFormatImpl(flags),
45 m_format (f)
46 {
47 }
48
49 bool
FormatObject(ValueObject * valobj,std::string & dest) const50 TypeFormatImpl_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 (®_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
137 std::string
GetDescription()138 TypeFormatImpl_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
TypeFormatImpl_EnumType(ConstString type_name,const TypeFormatImpl::Flags & flags)149 TypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name,
150 const TypeFormatImpl::Flags& flags) :
151 TypeFormatImpl(flags),
152 m_enum_type(type_name),
153 m_types()
154 {
155 }
156
157 bool
FormatObject(ValueObject * valobj,std::string & dest) const158 TypeFormatImpl_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
222 std::string
GetDescription()223 TypeFormatImpl_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