1 //===-- ValueObjectMemory.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/ValueObject/ValueObjectMemory.h"
10 #include "lldb/Core/Value.h"
11 #include "lldb/Symbol/Type.h"
12 #include "lldb/Target/ExecutionContext.h"
13 #include "lldb/Target/Target.h"
14 #include "lldb/Utility/DataExtractor.h"
15 #include "lldb/Utility/Scalar.h"
16 #include "lldb/Utility/Status.h"
17 #include "lldb/ValueObject/ValueObject.h"
18 #include "lldb/lldb-types.h"
19 #include "llvm/Support/ErrorHandling.h"
25 namespace lldb_private
{
26 class ExecutionContextScope
;
30 using namespace lldb_private
;
32 ValueObjectSP
ValueObjectMemory::Create(ExecutionContextScope
*exe_scope
,
34 const Address
&address
,
35 lldb::TypeSP
&type_sp
) {
36 auto manager_sp
= ValueObjectManager::Create();
37 return (new ValueObjectMemory(exe_scope
, *manager_sp
, name
, address
, type_sp
))
41 ValueObjectSP
ValueObjectMemory::Create(ExecutionContextScope
*exe_scope
,
43 const Address
&address
,
44 const CompilerType
&ast_type
) {
45 auto manager_sp
= ValueObjectManager::Create();
46 return (new ValueObjectMemory(exe_scope
, *manager_sp
, name
, address
,
51 ValueObjectMemory::ValueObjectMemory(ExecutionContextScope
*exe_scope
,
52 ValueObjectManager
&manager
,
54 const Address
&address
,
55 lldb::TypeSP
&type_sp
)
56 : ValueObject(exe_scope
, manager
), m_address(address
), m_type_sp(type_sp
),
58 // Do not attempt to construct one of these objects with no variable!
59 assert(m_type_sp
.get() != nullptr);
60 SetName(ConstString(name
));
61 m_value
.SetContext(Value::ContextType::LLDBType
, m_type_sp
.get());
62 TargetSP
target_sp(GetTargetSP());
63 lldb::addr_t load_address
= m_address
.GetLoadAddress(target_sp
.get());
64 if (load_address
!= LLDB_INVALID_ADDRESS
) {
65 m_value
.SetValueType(Value::ValueType::LoadAddress
);
66 m_value
.GetScalar() = load_address
;
68 lldb::addr_t file_address
= m_address
.GetFileAddress();
69 if (file_address
!= LLDB_INVALID_ADDRESS
) {
70 m_value
.SetValueType(Value::ValueType::FileAddress
);
71 m_value
.GetScalar() = file_address
;
73 m_value
.GetScalar() = m_address
.GetOffset();
74 m_value
.SetValueType(Value::ValueType::Scalar
);
79 ValueObjectMemory::ValueObjectMemory(ExecutionContextScope
*exe_scope
,
80 ValueObjectManager
&manager
,
82 const Address
&address
,
83 const CompilerType
&ast_type
)
84 : ValueObject(exe_scope
, manager
), m_address(address
), m_type_sp(),
85 m_compiler_type(ast_type
) {
86 // Do not attempt to construct one of these objects with no variable!
87 assert(m_compiler_type
.IsValid());
89 TargetSP
target_sp(GetTargetSP());
91 SetName(ConstString(name
));
92 m_value
.SetCompilerType(m_compiler_type
);
93 lldb::addr_t load_address
= m_address
.GetLoadAddress(target_sp
.get());
94 if (load_address
!= LLDB_INVALID_ADDRESS
) {
95 m_value
.SetValueType(Value::ValueType::LoadAddress
);
96 m_value
.GetScalar() = load_address
;
98 lldb::addr_t file_address
= m_address
.GetFileAddress();
99 if (file_address
!= LLDB_INVALID_ADDRESS
) {
100 m_value
.SetValueType(Value::ValueType::FileAddress
);
101 m_value
.GetScalar() = file_address
;
103 m_value
.GetScalar() = m_address
.GetOffset();
104 m_value
.SetValueType(Value::ValueType::Scalar
);
109 ValueObjectMemory::~ValueObjectMemory() = default;
111 CompilerType
ValueObjectMemory::GetCompilerTypeImpl() {
113 return m_type_sp
->GetForwardCompilerType();
114 return m_compiler_type
;
117 ConstString
ValueObjectMemory::GetTypeName() {
119 return m_type_sp
->GetName();
120 return m_compiler_type
.GetTypeName();
123 ConstString
ValueObjectMemory::GetDisplayTypeName() {
125 return m_type_sp
->GetForwardCompilerType().GetDisplayTypeName();
126 return m_compiler_type
.GetDisplayTypeName();
129 llvm::Expected
<uint32_t> ValueObjectMemory::CalculateNumChildren(uint32_t max
) {
131 auto child_count
= m_type_sp
->GetNumChildren(true);
134 return *child_count
<= max
? *child_count
: max
;
137 ExecutionContext
exe_ctx(GetExecutionContextRef());
138 const bool omit_empty_base_classes
= true;
140 m_compiler_type
.GetNumChildren(omit_empty_base_classes
, &exe_ctx
);
143 return *child_count
<= max
? *child_count
: max
;
146 std::optional
<uint64_t> ValueObjectMemory::GetByteSize() {
147 ExecutionContext
exe_ctx(GetExecutionContextRef());
149 return m_type_sp
->GetByteSize(exe_ctx
.GetBestExecutionContextScope());
150 return m_compiler_type
.GetByteSize(exe_ctx
.GetBestExecutionContextScope());
153 lldb::ValueType
ValueObjectMemory::GetValueType() const {
154 // RETHINK: Should this be inherited from somewhere?
155 return lldb::eValueTypeVariableGlobal
;
158 bool ValueObjectMemory::UpdateValue() {
159 SetValueIsValid(false);
162 ExecutionContext
exe_ctx(GetExecutionContextRef());
164 Target
*target
= exe_ctx
.GetTargetPtr();
166 m_data
.SetByteOrder(target
->GetArchitecture().GetByteOrder());
167 m_data
.SetAddressByteSize(target
->GetArchitecture().GetAddressByteSize());
170 Value
old_value(m_value
);
171 if (m_address
.IsValid()) {
172 Value::ValueType value_type
= m_value
.GetValueType();
174 switch (value_type
) {
175 case Value::ValueType::Invalid
:
176 m_error
= Status::FromErrorString("Invalid value");
178 case Value::ValueType::Scalar
:
179 // The variable value is in the Scalar value inside the m_value. We can
180 // point our m_data right to it.
181 m_error
= m_value
.GetValueAsData(&exe_ctx
, m_data
, GetModule().get());
184 case Value::ValueType::FileAddress
:
185 case Value::ValueType::LoadAddress
:
186 case Value::ValueType::HostAddress
:
187 // The DWARF expression result was an address in the inferior process. If
188 // this variable is an aggregate type, we just need the address as the
189 // main value as all child variable objects will rely upon this location
190 // and add an offset and then read their own values as needed. If this
191 // variable is a simple type, we read all data for it into m_data. Make
192 // sure this type has a value before we try and read it
194 // If we have a file address, convert it to a load address if we can.
195 if (value_type
== Value::ValueType::FileAddress
&&
196 exe_ctx
.GetProcessPtr()) {
197 lldb::addr_t load_addr
= m_address
.GetLoadAddress(target
);
198 if (load_addr
!= LLDB_INVALID_ADDRESS
) {
199 m_value
.SetValueType(Value::ValueType::LoadAddress
);
200 m_value
.GetScalar() = load_addr
;
204 if (!CanProvideValue()) {
205 // this value object represents an aggregate type whose children have
206 // values, but this object does not. So we say we are changed if our
207 // location has changed.
208 SetValueDidChange(value_type
!= old_value
.GetValueType() ||
209 m_value
.GetScalar() != old_value
.GetScalar());
211 // Copy the Value and set the context to use our Variable so it can
212 // extract read its value into m_data appropriately
213 Value
value(m_value
);
215 value
.SetContext(Value::ContextType::LLDBType
, m_type_sp
.get());
217 value
.SetCompilerType(m_compiler_type
);
220 m_error
= value
.GetValueAsData(&exe_ctx
, m_data
, GetModule().get());
225 SetValueIsValid(m_error
.Success());
227 return m_error
.Success();
230 bool ValueObjectMemory::IsInScope() {
231 // FIXME: Maybe try to read the memory address, and if that works, then
236 lldb::ModuleSP
ValueObjectMemory::GetModule() { return m_address
.GetModule(); }