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