Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/ValueObjectMemory.cpp
213764 views
1
//===-- ValueObjectMemory.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/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"
20
21
#include <cassert>
22
#include <memory>
23
#include <optional>
24
25
namespace lldb_private {
26
class ExecutionContextScope;
27
}
28
29
using namespace lldb;
30
using namespace lldb_private;
31
32
ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
33
llvm::StringRef name,
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))
38
->GetSP();
39
}
40
41
ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
42
llvm::StringRef name,
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,
47
ast_type))
48
->GetSP();
49
}
50
51
ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
52
ValueObjectManager &manager,
53
llvm::StringRef name,
54
const Address &address,
55
lldb::TypeSP &type_sp)
56
: ValueObject(exe_scope, manager), m_address(address), m_type_sp(type_sp),
57
m_compiler_type() {
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;
67
} else {
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;
72
} else {
73
m_value.GetScalar() = m_address.GetOffset();
74
m_value.SetValueType(Value::ValueType::Scalar);
75
}
76
}
77
}
78
79
ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
80
ValueObjectManager &manager,
81
llvm::StringRef name,
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());
88
89
TargetSP target_sp(GetTargetSP());
90
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;
97
} else {
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;
102
} else {
103
m_value.GetScalar() = m_address.GetOffset();
104
m_value.SetValueType(Value::ValueType::Scalar);
105
}
106
}
107
}
108
109
ValueObjectMemory::~ValueObjectMemory() = default;
110
111
CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
112
if (m_type_sp)
113
return m_type_sp->GetForwardCompilerType();
114
return m_compiler_type;
115
}
116
117
ConstString ValueObjectMemory::GetTypeName() {
118
if (m_type_sp)
119
return m_type_sp->GetName();
120
return m_compiler_type.GetTypeName();
121
}
122
123
ConstString ValueObjectMemory::GetDisplayTypeName() {
124
if (m_type_sp)
125
return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();
126
return m_compiler_type.GetDisplayTypeName();
127
}
128
129
llvm::Expected<uint32_t> ValueObjectMemory::CalculateNumChildren(uint32_t max) {
130
if (m_type_sp) {
131
auto child_count = m_type_sp->GetNumChildren(true);
132
if (!child_count)
133
return child_count;
134
return *child_count <= max ? *child_count : max;
135
}
136
137
ExecutionContext exe_ctx(GetExecutionContextRef());
138
const bool omit_empty_base_classes = true;
139
auto child_count =
140
m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
141
if (!child_count)
142
return child_count;
143
return *child_count <= max ? *child_count : max;
144
}
145
146
llvm::Expected<uint64_t> ValueObjectMemory::GetByteSize() {
147
ExecutionContext exe_ctx(GetExecutionContextRef());
148
if (m_type_sp) {
149
if (auto size =
150
m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope()))
151
return *size;
152
return llvm::createStringError("could not get byte size of memory object");
153
}
154
return m_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
155
}
156
157
lldb::ValueType ValueObjectMemory::GetValueType() const {
158
// RETHINK: Should this be inherited from somewhere?
159
return lldb::eValueTypeVariableGlobal;
160
}
161
162
bool ValueObjectMemory::UpdateValue() {
163
SetValueIsValid(false);
164
m_error.Clear();
165
166
ExecutionContext exe_ctx(GetExecutionContextRef());
167
168
Target *target = exe_ctx.GetTargetPtr();
169
if (target) {
170
m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
171
m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
172
}
173
174
Value old_value(m_value);
175
if (m_address.IsValid()) {
176
Value::ValueType value_type = m_value.GetValueType();
177
178
switch (value_type) {
179
case Value::ValueType::Invalid:
180
m_error = Status::FromErrorString("Invalid value");
181
return false;
182
case Value::ValueType::Scalar:
183
// The variable value is in the Scalar value inside the m_value. We can
184
// point our m_data right to it.
185
m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
186
break;
187
188
case Value::ValueType::FileAddress:
189
case Value::ValueType::LoadAddress:
190
case Value::ValueType::HostAddress:
191
// The DWARF expression result was an address in the inferior process. If
192
// this variable is an aggregate type, we just need the address as the
193
// main value as all child variable objects will rely upon this location
194
// and add an offset and then read their own values as needed. If this
195
// variable is a simple type, we read all data for it into m_data. Make
196
// sure this type has a value before we try and read it
197
198
// If we have a file address, convert it to a load address if we can.
199
if (value_type == Value::ValueType::FileAddress &&
200
exe_ctx.GetProcessPtr()) {
201
lldb::addr_t load_addr = m_address.GetLoadAddress(target);
202
if (load_addr != LLDB_INVALID_ADDRESS) {
203
m_value.SetValueType(Value::ValueType::LoadAddress);
204
m_value.GetScalar() = load_addr;
205
}
206
}
207
208
if (!CanProvideValue()) {
209
// this value object represents an aggregate type whose children have
210
// values, but this object does not. So we say we are changed if our
211
// location has changed.
212
SetValueDidChange(value_type != old_value.GetValueType() ||
213
m_value.GetScalar() != old_value.GetScalar());
214
} else {
215
// Copy the Value and set the context to use our Variable so it can
216
// extract read its value into m_data appropriately
217
Value value(m_value);
218
if (m_type_sp)
219
value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());
220
else {
221
value.SetCompilerType(m_compiler_type);
222
}
223
224
m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
225
}
226
break;
227
}
228
229
SetValueIsValid(m_error.Success());
230
}
231
return m_error.Success();
232
}
233
234
bool ValueObjectMemory::IsInScope() {
235
// FIXME: Maybe try to read the memory address, and if that works, then
236
// we are in scope?
237
return true;
238
}
239
240
lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); }
241
242