LLDB mainline
ValueObjectVTable.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
10#include "lldb/Core/Module.h"
15#include "lldb/lldb-defines.h"
17#include "lldb/lldb-forward.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
24public:
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) {
29 SetName(ConstString(llvm::formatv("[{0}]", func_idx).str()));
30 }
31
32 ~ValueObjectVTableChild() override = default;
33
34 std::optional<uint64_t> GetByteSize() override { return m_addr_size; };
35
36 llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override {
37 return 0;
38 };
39
40 ValueType GetValueType() const override { return eValueTypeVTableEntry; };
41
42 bool IsInScope() override {
43 if (ValueObject *parent = GetParent())
44 return parent->IsInScope();
45 return false;
46 };
47
48protected:
49 bool UpdateValue() override {
50 SetValueIsValid(false);
51 m_value.Clear();
52 ValueObject *parent = GetParent();
53 if (!parent) {
54 m_error.SetErrorString("owning vtable object not valid");
55 return false;
56 }
57
58 addr_t parent_addr = parent->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
59 if (parent_addr == LLDB_INVALID_ADDRESS) {
60 m_error.SetErrorString("invalid vtable address");
61 return false;
62 }
63
64 ProcessSP process_sp = GetProcessSP();
65 if (!process_sp) {
66 m_error.SetErrorString("no process");
67 return false;
68 }
69
70 TargetSP target_sp = GetTargetSP();
71 if (!target_sp) {
72 m_error.SetErrorString("no target");
73 return false;
74 }
75
76 // Each `vtable_entry_addr` points to the function pointer.
77 addr_t vtable_entry_addr = parent_addr + m_func_idx * m_addr_size;
78 addr_t vfunc_ptr =
79 process_sp->ReadPointerFromMemory(vtable_entry_addr, m_error);
80 if (m_error.Fail()) {
82 "failed to read virtual function entry 0x%16.16" PRIx64,
83 vtable_entry_addr);
84 return false;
85 }
86
87
88 // Set our value to be the load address of the function pointer in memory
89 // and our type to be the function pointer type.
90 m_value.SetValueType(Value::ValueType::LoadAddress);
91 m_value.GetScalar() = vtable_entry_addr;
92
93 // See if our resolved address points to a function in the debug info. If
94 // it does, then we can report the type as a function prototype for this
95 // function.
96 Function *function = nullptr;
97 Address resolved_vfunc_ptr_address;
98 target_sp->ResolveLoadAddress(vfunc_ptr, resolved_vfunc_ptr_address);
99 if (resolved_vfunc_ptr_address.IsValid())
100 function = resolved_vfunc_ptr_address.CalculateSymbolContextFunction();
101 if (function) {
103 } else {
104 // Set our value's compiler type to a generic function protoype so that
105 // it displays as a hex function pointer for the value and the summary
106 // will display the address description.
107
108 // Get the original type that this vtable is based off of so we can get
109 // the language from it correctly.
110 ValueObject *val = parent->GetParent();
111 auto type_system = target_sp->GetScratchTypeSystemForLanguage(
113 if (type_system) {
115 (*type_system)->CreateGenericFunctionPrototype().GetPointerType());
116 } else {
117 consumeError(type_system.takeError());
118 }
119 }
120
121 // Now read our value into m_data so that our we can use the default
122 // summary provider for C++ for function pointers which will get the
123 // address description for our function pointer.
124 if (m_error.Success()) {
125 const bool thread_and_frame_only_if_stopped = true;
126 ExecutionContext exe_ctx(
127 GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
128 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
129 }
130 SetValueDidChange(true);
131 SetValueIsValid(true);
132 return true;
133 };
134
136 return m_value.GetCompilerType();
137 };
138
139 const uint32_t m_func_idx;
140 const uint64_t m_addr_size;
141
142private:
143 // For ValueObject only
147};
148
150 return (new ValueObjectVTable(parent))->GetSP();
151}
152
154 : ValueObject(parent) {
156}
157
158std::optional<uint64_t> ValueObjectVTable::GetByteSize() {
159 if (m_vtable_symbol)
161 return std::nullopt;
162}
163
164llvm::Expected<uint32_t> ValueObjectVTable::CalculateNumChildren(uint32_t max) {
165 if (UpdateValueIfNeeded(false))
166 return m_num_vtable_entries <= max ? m_num_vtable_entries : max;
167 return 0;
168}
169
171
173 if (m_vtable_symbol)
174 return m_vtable_symbol->GetName();
175 return ConstString();
176}
177
179
181 if (m_vtable_symbol)
183 return ConstString();
184}
185
187
189 bool synthetic_array_member,
190 int32_t synthetic_index) {
191 if (synthetic_array_member)
192 return nullptr;
193 return new ValueObjectVTableChild(*this, idx, m_addr_size);
194}
195
197 m_error.Clear();
199 SetValueIsValid(false);
201 ValueObject *parent = GetParent();
202 if (!parent) {
203 m_error.SetErrorString("no parent object");
204 return false;
205 }
206
207 ProcessSP process_sp = GetProcessSP();
208 if (!process_sp) {
209 m_error.SetErrorString("no process");
210 return false;
211 }
212
213 const LanguageType language = parent->GetObjectRuntimeLanguage();
214 LanguageRuntime *language_runtime = process_sp->GetLanguageRuntime(language);
215
216 if (language_runtime == nullptr) {
218 "no language runtime support for the language \"%s\"",
220 return false;
221 }
222
223 // Get the vtable information from the language runtime.
224 llvm::Expected<LanguageRuntime::VTableInfo> vtable_info_or_err =
225 language_runtime->GetVTableInfo(*parent, /*check_type=*/true);
226 if (!vtable_info_or_err) {
227 m_error = vtable_info_or_err.takeError();
228 return false;
229 }
230
231 TargetSP target_sp = GetTargetSP();
232 const addr_t vtable_start_addr =
233 vtable_info_or_err->addr.GetLoadAddress(target_sp.get());
234
235 m_vtable_symbol = vtable_info_or_err->symbol;
236 if (!m_vtable_symbol) {
238 "no vtable symbol found containing 0x%" PRIx64, vtable_start_addr);
239 return false;
240 }
241
242 // Now that we know it's a vtable, we update the object's state.
244
245 // Calculate the number of entries
248 "vtable symbol \"%s\" doesn't have a valid size",
250 return false;
251 }
252
253 m_addr_size = process_sp->GetAddressByteSize();
254 const addr_t vtable_end_addr =
255 m_vtable_symbol->GetLoadAddress(target_sp.get()) +
257 m_num_vtable_entries = (vtable_end_addr - vtable_start_addr) / m_addr_size;
258
260 m_value.GetScalar() = parent->GetAddressOf();
261 auto type_system_or_err =
262 target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC_plus_plus);
263 if (type_system_or_err) {
265 (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeUnsignedLong));
266 } else {
267 consumeError(type_system_or_err.takeError());
268 }
269 SetValueDidChange(true);
270 SetValueIsValid(true);
271 return true;
272}
273
275
ValueObjectVTableChild(ValueObject &parent, uint32_t func_idx, uint64_t addr_size)
llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max) override
Should only be called by ValueObject::GetNumChildren().
ValueObjectVTableChild(const ValueObjectVTableChild &)=delete
~ValueObjectVTableChild() override=default
CompilerType GetCompilerTypeImpl() override
std::optional< uint64_t > GetByteSize() override
const ValueObjectVTableChild & operator=(const ValueObjectVTableChild &)=delete
ValueType GetValueType() const override
A section + offset based address class.
Definition: Address.h:62
Function * CalculateSymbolContextFunction() const
Definition: Address.cpp:871
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:355
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
A uniqued constant string class.
Definition: ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:214
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A class that describes a function.
Definition: Function.h:399
CompilerType GetCompilerType()
Definition: Function.cpp:559
virtual llvm::Expected< VTableInfo > GetVTableInfo(ValueObject &in_value, bool check_type)
Get the vtable information for a given value.
static const char * GetNameForLanguageType(lldb::LanguageType language)
Definition: Language.cpp:265
ConstString GetDemangledName() const
Demangled name get accessor.
Definition: Mangled.cpp:262
void Clear()
Clear the object state.
Definition: Status.cpp:167
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:247
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:233
bool Success() const
Test for success condition.
Definition: Status.cpp:279
lldb::addr_t GetLoadAddress(Target *target) const
Definition: Symbol.cpp:545
bool GetByteSizeIsValid() const
Definition: Symbol.h:208
Mangled & GetMangled()
Definition: Symbol.h:146
lldb::addr_t GetByteSize() const
Definition: Symbol.cpp:472
ConstString GetName() const
Definition: Symbol.cpp:552
ConstString GetDisplayName() const
Definition: Symbol.cpp:173
A class that represents a virtual function table for a C++ class.
const Symbol * m_vtable_symbol
The symbol for the C++ virtual function table.
llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max) override
Should only be called by ValueObject::GetNumChildren().
uint32_t m_addr_size
Cache the address size in bytes to avoid checking with the process to many times.
ConstString GetQualifiedTypeName() override
static lldb::ValueObjectSP Create(ValueObject &parent)
lldb::ValueType GetValueType() const override
ValueObjectVTable(ValueObject &parent)
std::optional< uint64_t > GetByteSize() override
ConstString GetTypeName() override
uint32_t m_num_vtable_entries
Cache the number of vtable children when we update the value.
ConstString GetDisplayTypeName() override
CompilerType GetCompilerTypeImpl() override
ValueObject * CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override
Should only be called by ValueObject::GetChildAtIndex().
void SetValueIsValid(bool valid)
Definition: ValueObject.h:976
virtual bool IsInScope()
Definition: ValueObject.h:420
struct lldb_private::ValueObject::Bitflags m_flags
Status m_error
An error object that can describe any errors that occur when updating values.
Definition: ValueObject.h:850
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:338
DataExtractor m_data
A data extractor that can be used to extract the value.
Definition: ValueObject.h:846
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
void SetValueDidChange(bool value_changed)
Definition: ValueObject.h:972
virtual lldb::ModuleSP GetModule()
Return the module associated with this value object in case the value is from an executable file and ...
lldb::LanguageType GetObjectRuntimeLanguage()
Definition: ValueObject.h:373
virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address=true, AddressType *address_type=nullptr)
bool UpdateValueIfNeeded(bool update_format=true)
void SetName(ConstString name)
Change the name of the current ValueObject.
Definition: ValueObject.h:550
lldb::TargetSP GetTargetSP() const
Definition: ValueObject.h:334
virtual ValueObject * GetParent()
Definition: ValueObject.h:748
virtual void SetFormat(lldb::Format format)
Definition: ValueObject.h:700
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:330
const Scalar & GetScalar() const
Definition: Value.h:112
Status GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, Module *module)
Definition: Value.cpp:315
@ LoadAddress
A load address value.
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
void SetValueType(ValueType value_type)
Definition: Value.h:89
const CompilerType & GetCompilerType()
Definition: Value.cpp:239
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
@ eBasicTypeUnsignedLong
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:472
LanguageType
Programming language type.
@ eLanguageTypeC_plus_plus
ISO C++:1998.
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
uint64_t addr_t
Definition: lldb-types.h:79
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:436
@ eValueTypeVTableEntry
function pointer in virtual function table
@ eValueTypeVTable
virtual function table