[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / lldb / source / Core / ValueObjectVTable.cpp
blob177ae4167a1d455bcde83e84896a992c299a0179
1 //===-- ValueObjectVTable.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 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/ValueObjectVTable.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/Core/ValueObjectChild.h"
12 #include "lldb/Symbol/Function.h"
13 #include "lldb/Target/Language.h"
14 #include "lldb/Target/LanguageRuntime.h"
15 #include "lldb/lldb-defines.h"
16 #include "lldb/lldb-enumerations.h"
17 #include "lldb/lldb-forward.h"
18 #include "lldb/lldb-private-enumerations.h"
20 using namespace lldb;
21 using namespace lldb_private;
23 class ValueObjectVTableChild : public ValueObject {
24 public:
25 ValueObjectVTableChild(ValueObject &parent, uint32_t func_idx,
26 uint64_t addr_size)
27 : ValueObject(parent), m_func_idx(func_idx), m_addr_size(addr_size) {
28 SetFormat(eFormatPointer);
29 SetName(ConstString(llvm::formatv("[{0}]", func_idx).str()));
32 ~ValueObjectVTableChild() override = default;
34 std::optional<uint64_t> GetByteSize() override { return m_addr_size; };
36 size_t CalculateNumChildren(uint32_t max) override { return 0; };
38 ValueType GetValueType() const override { return eValueTypeVTableEntry; };
40 bool IsInScope() override {
41 if (ValueObject *parent = GetParent())
42 return parent->IsInScope();
43 return false;
46 protected:
47 bool UpdateValue() override {
48 SetValueIsValid(false);
49 m_value.Clear();
50 ValueObject *parent = GetParent();
51 if (!parent) {
52 m_error.SetErrorString("owning vtable object not valid");
53 return false;
56 addr_t parent_addr = parent->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
57 if (parent_addr == LLDB_INVALID_ADDRESS) {
58 m_error.SetErrorString("invalid vtable address");
59 return false;
62 ProcessSP process_sp = GetProcessSP();
63 if (!process_sp) {
64 m_error.SetErrorString("no process");
65 return false;
68 TargetSP target_sp = GetTargetSP();
69 if (!target_sp) {
70 m_error.SetErrorString("no target");
71 return false;
74 // Each `vtable_entry_addr` points to the function pointer.
75 addr_t vtable_entry_addr = parent_addr + m_func_idx * m_addr_size;
76 addr_t vfunc_ptr =
77 process_sp->ReadPointerFromMemory(vtable_entry_addr, m_error);
78 if (m_error.Fail()) {
79 m_error.SetErrorStringWithFormat(
80 "failed to read virtual function entry 0x%16.16" PRIx64,
81 vtable_entry_addr);
82 return false;
86 // Set our value to be the load address of the function pointer in memory
87 // and our type to be the function pointer type.
88 m_value.SetValueType(Value::ValueType::LoadAddress);
89 m_value.GetScalar() = vtable_entry_addr;
91 // See if our resolved address points to a function in the debug info. If
92 // it does, then we can report the type as a function prototype for this
93 // function.
94 Function *function = nullptr;
95 Address resolved_vfunc_ptr_address;
96 target_sp->ResolveLoadAddress(vfunc_ptr, resolved_vfunc_ptr_address);
97 if (resolved_vfunc_ptr_address.IsValid())
98 function = resolved_vfunc_ptr_address.CalculateSymbolContextFunction();
99 if (function) {
100 m_value.SetCompilerType(function->GetCompilerType().GetPointerType());
101 } else {
102 // Set our value's compiler type to a generic function protoype so that
103 // it displays as a hex function pointer for the value and the summary
104 // will display the address description.
106 // Get the original type that this vtable is based off of so we can get
107 // the language from it correctly.
108 ValueObject *val = parent->GetParent();
109 auto type_system = target_sp->GetScratchTypeSystemForLanguage(
110 val ? val->GetObjectRuntimeLanguage() : eLanguageTypeC_plus_plus);
111 if (type_system) {
112 m_value.SetCompilerType(
113 (*type_system)->CreateGenericFunctionPrototype().GetPointerType());
114 } else {
115 consumeError(type_system.takeError());
119 // Now read our value into m_data so that our we can use the default
120 // summary provider for C++ for function pointers which will get the
121 // address description for our function pointer.
122 if (m_error.Success()) {
123 const bool thread_and_frame_only_if_stopped = true;
124 ExecutionContext exe_ctx(
125 GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
126 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
128 SetValueDidChange(true);
129 SetValueIsValid(true);
130 return true;
133 CompilerType GetCompilerTypeImpl() override {
134 return m_value.GetCompilerType();
137 const uint32_t m_func_idx;
138 const uint64_t m_addr_size;
140 private:
141 // For ValueObject only
142 ValueObjectVTableChild(const ValueObjectVTableChild &) = delete;
143 const ValueObjectVTableChild &
144 operator=(const ValueObjectVTableChild &) = delete;
147 ValueObjectSP ValueObjectVTable::Create(ValueObject &parent) {
148 return (new ValueObjectVTable(parent))->GetSP();
151 ValueObjectVTable::ValueObjectVTable(ValueObject &parent)
152 : ValueObject(parent) {
153 SetFormat(eFormatPointer);
156 std::optional<uint64_t> ValueObjectVTable::GetByteSize() {
157 if (m_vtable_symbol)
158 return m_vtable_symbol->GetByteSize();
159 return std::nullopt;
162 size_t ValueObjectVTable::CalculateNumChildren(uint32_t max) {
163 if (UpdateValueIfNeeded(false))
164 return m_num_vtable_entries <= max ? m_num_vtable_entries : max;
165 return 0;
168 ValueType ValueObjectVTable::GetValueType() const { return eValueTypeVTable; }
170 ConstString ValueObjectVTable::GetTypeName() {
171 if (m_vtable_symbol)
172 return m_vtable_symbol->GetName();
173 return ConstString();
176 ConstString ValueObjectVTable::GetQualifiedTypeName() { return GetTypeName(); }
178 ConstString ValueObjectVTable::GetDisplayTypeName() {
179 if (m_vtable_symbol)
180 return m_vtable_symbol->GetDisplayName();
181 return ConstString();
184 bool ValueObjectVTable::IsInScope() { return GetParent()->IsInScope(); }
186 ValueObject *ValueObjectVTable::CreateChildAtIndex(size_t idx,
187 bool synthetic_array_member,
188 int32_t synthetic_index) {
189 if (synthetic_array_member)
190 return nullptr;
191 return new ValueObjectVTableChild(*this, idx, m_addr_size);
194 bool ValueObjectVTable::UpdateValue() {
195 m_error.Clear();
196 m_flags.m_children_count_valid = false;
197 SetValueIsValid(false);
198 m_num_vtable_entries = 0;
199 ValueObject *parent = GetParent();
200 if (!parent) {
201 m_error.SetErrorString("no parent object");
202 return false;
205 ProcessSP process_sp = GetProcessSP();
206 if (!process_sp) {
207 m_error.SetErrorString("no process");
208 return false;
211 const LanguageType language = parent->GetObjectRuntimeLanguage();
212 LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(language);
214 if (language_runtime == nullptr) {
215 m_error.SetErrorStringWithFormat(
216 "no language runtime support for the language \"%s\"",
217 Language::GetNameForLanguageType(language));
218 return false;
221 // Get the vtable information from the language runtime.
222 llvm::Expected<LanguageRuntime::VTableInfo> vtable_info_or_err =
223 language_runtime->GetVTableInfo(*parent, /*check_type=*/true);
224 if (!vtable_info_or_err) {
225 m_error = vtable_info_or_err.takeError();
226 return false;
229 TargetSP target_sp = GetTargetSP();
230 const addr_t vtable_start_addr =
231 vtable_info_or_err->addr.GetLoadAddress(target_sp.get());
233 m_vtable_symbol = vtable_info_or_err->symbol;
234 if (!m_vtable_symbol) {
235 m_error.SetErrorStringWithFormat(
236 "no vtable symbol found containing 0x%" PRIx64, vtable_start_addr);
237 return false;
240 // Now that we know it's a vtable, we update the object's state.
241 SetName(GetTypeName());
243 // Calculate the number of entries
244 if (!m_vtable_symbol->GetByteSizeIsValid()) {
245 m_error.SetErrorStringWithFormat(
246 "vtable symbol \"%s\" doesn't have a valid size",
247 m_vtable_symbol->GetMangled().GetDemangledName().GetCString());
248 return false;
251 m_addr_size = process_sp->GetAddressByteSize();
252 const addr_t vtable_end_addr =
253 m_vtable_symbol->GetLoadAddress(target_sp.get()) +
254 m_vtable_symbol->GetByteSize();
255 m_num_vtable_entries = (vtable_end_addr - vtable_start_addr) / m_addr_size;
257 m_value.SetValueType(Value::ValueType::LoadAddress);
258 m_value.GetScalar() = parent->GetAddressOf();
259 auto type_system_or_err =
260 target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC_plus_plus);
261 if (type_system_or_err) {
262 m_value.SetCompilerType(
263 (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeUnsignedLong));
264 } else {
265 consumeError(type_system_or_err.takeError());
267 SetValueDidChange(true);
268 SetValueIsValid(true);
269 return true;
272 CompilerType ValueObjectVTable::GetCompilerTypeImpl() { return CompilerType(); }
274 ValueObjectVTable::~ValueObjectVTable() = default;