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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/source/DataFormatters/TypeFormat.cpp