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