Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/ValueObjectRegister.cpp
213764 views
1
//===-- ValueObjectRegister.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/ValueObjectRegister.h"
10
11
#include "lldb/Core/Module.h"
12
#include "lldb/Core/Value.h"
13
#include "lldb/Symbol/CompilerType.h"
14
#include "lldb/Symbol/TypeSystem.h"
15
#include "lldb/Target/ExecutionContext.h"
16
#include "lldb/Target/Process.h"
17
#include "lldb/Target/RegisterContext.h"
18
#include "lldb/Target/StackFrame.h"
19
#include "lldb/Target/Target.h"
20
#include "lldb/Utility/DataExtractor.h"
21
#include "lldb/Utility/LLDBLog.h"
22
#include "lldb/Utility/Log.h"
23
#include "lldb/Utility/Scalar.h"
24
#include "lldb/Utility/Status.h"
25
#include "lldb/Utility/Stream.h"
26
27
#include "llvm/ADT/StringRef.h"
28
29
#include <cassert>
30
#include <memory>
31
#include <optional>
32
33
namespace lldb_private {
34
class ExecutionContextScope;
35
}
36
37
using namespace lldb;
38
using namespace lldb_private;
39
40
#pragma mark ValueObjectRegisterSet
41
42
ValueObjectSP
43
ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
44
lldb::RegisterContextSP &reg_ctx_sp,
45
uint32_t set_idx) {
46
auto manager_sp = ValueObjectManager::Create();
47
return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
48
set_idx))
49
->GetSP();
50
}
51
52
ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53
ValueObjectManager &manager,
54
lldb::RegisterContextSP &reg_ctx,
55
uint32_t reg_set_idx)
56
: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
57
m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
58
assert(reg_ctx);
59
m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
60
if (m_reg_set) {
61
m_name.SetCString(m_reg_set->name);
62
}
63
}
64
65
ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66
67
CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68
return CompilerType();
69
}
70
71
ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72
73
ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74
return ConstString();
75
}
76
77
llvm::Expected<uint32_t>
78
ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
79
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
80
if (reg_set) {
81
auto reg_count = reg_set->num_registers;
82
return reg_count <= max ? reg_count : max;
83
}
84
return 0;
85
}
86
87
llvm::Expected<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
88
89
bool ValueObjectRegisterSet::UpdateValue() {
90
m_error.Clear();
91
SetValueDidChange(false);
92
ExecutionContext exe_ctx(GetExecutionContextRef());
93
StackFrame *frame = exe_ctx.GetFramePtr();
94
if (frame == nullptr)
95
m_reg_ctx_sp.reset();
96
else {
97
m_reg_ctx_sp = frame->GetRegisterContext();
98
if (m_reg_ctx_sp) {
99
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
100
if (reg_set == nullptr)
101
m_reg_ctx_sp.reset();
102
else if (m_reg_set != reg_set) {
103
SetValueDidChange(true);
104
m_name.SetCString(reg_set->name);
105
}
106
}
107
}
108
if (m_reg_ctx_sp) {
109
SetValueIsValid(true);
110
} else {
111
SetValueIsValid(false);
112
m_error = Status::FromErrorString("no register context");
113
m_children.Clear();
114
}
115
return m_error.Success();
116
}
117
118
ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {
119
if (m_reg_ctx_sp && m_reg_set) {
120
return new ValueObjectRegister(
121
*this, m_reg_ctx_sp,
122
m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
123
}
124
return nullptr;
125
}
126
127
lldb::ValueObjectSP
128
ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
129
bool can_create) {
130
ValueObject *valobj = nullptr;
131
if (m_reg_ctx_sp && m_reg_set) {
132
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
133
if (reg_info != nullptr)
134
valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
135
}
136
if (valobj)
137
return valobj->GetSP();
138
else
139
return ValueObjectSP();
140
}
141
142
llvm::Expected<size_t>
143
ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
144
if (m_reg_ctx_sp && m_reg_set) {
145
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
146
if (reg_info != nullptr)
147
return reg_info->kinds[eRegisterKindLLDB];
148
}
149
return llvm::createStringError("Type has no child named '%s'",
150
name.str().c_str());
151
}
152
153
#pragma mark -
154
#pragma mark ValueObjectRegister
155
156
void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
157
if (reg_info) {
158
m_reg_info = *reg_info;
159
if (reg_info->name)
160
m_name.SetCString(reg_info->name);
161
else if (reg_info->alt_name)
162
m_name.SetCString(reg_info->alt_name);
163
}
164
}
165
166
ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
167
lldb::RegisterContextSP &reg_ctx_sp,
168
const RegisterInfo *reg_info)
169
: ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
170
m_reg_value(), m_type_name(), m_compiler_type() {
171
assert(reg_ctx_sp.get());
172
ConstructObject(reg_info);
173
}
174
175
ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
176
lldb::RegisterContextSP &reg_ctx_sp,
177
const RegisterInfo *reg_info) {
178
auto manager_sp = ValueObjectManager::Create();
179
return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
180
->GetSP();
181
}
182
183
ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
184
ValueObjectManager &manager,
185
lldb::RegisterContextSP &reg_ctx,
186
const RegisterInfo *reg_info)
187
: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
188
m_reg_value(), m_type_name(), m_compiler_type() {
189
assert(reg_ctx);
190
ConstructObject(reg_info);
191
}
192
193
ValueObjectRegister::~ValueObjectRegister() = default;
194
195
CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
196
if (!m_compiler_type.IsValid()) {
197
ExecutionContext exe_ctx(GetExecutionContextRef());
198
if (auto *target = exe_ctx.GetTargetPtr()) {
199
if (auto *exe_module = target->GetExecutableModulePointer()) {
200
auto type_system_or_err =
201
exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
202
if (auto err = type_system_or_err.takeError()) {
203
LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
204
"Unable to get CompilerType from TypeSystem: {0}");
205
} else {
206
if (auto ts = *type_system_or_err)
207
m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
208
m_reg_info.encoding, m_reg_info.byte_size * 8);
209
}
210
}
211
}
212
}
213
return m_compiler_type;
214
}
215
216
ConstString ValueObjectRegister::GetTypeName() {
217
if (m_type_name.IsEmpty())
218
m_type_name = GetCompilerType().GetTypeName();
219
return m_type_name;
220
}
221
222
llvm::Expected<uint32_t>
223
ValueObjectRegister::CalculateNumChildren(uint32_t max) {
224
ExecutionContext exe_ctx(GetExecutionContextRef());
225
auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
226
if (!children_count)
227
return children_count;
228
return *children_count <= max ? *children_count : max;
229
}
230
231
llvm::Expected<uint64_t> ValueObjectRegister::GetByteSize() {
232
return m_reg_info.byte_size;
233
}
234
235
bool ValueObjectRegister::UpdateValue() {
236
m_error.Clear();
237
ExecutionContext exe_ctx(GetExecutionContextRef());
238
StackFrame *frame = exe_ctx.GetFramePtr();
239
if (frame == nullptr) {
240
m_reg_ctx_sp.reset();
241
m_reg_value.Clear();
242
}
243
244
if (m_reg_ctx_sp) {
245
RegisterValue m_old_reg_value(m_reg_value);
246
if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
247
if (m_reg_value.GetData(m_data)) {
248
Process *process = exe_ctx.GetProcessPtr();
249
if (process)
250
m_data.SetAddressByteSize(process->GetAddressByteSize());
251
m_value.SetContext(Value::ContextType::RegisterInfo,
252
(void *)&m_reg_info);
253
m_value.SetValueType(Value::ValueType::HostAddress);
254
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
255
SetValueIsValid(true);
256
SetValueDidChange(!(m_old_reg_value == m_reg_value));
257
return true;
258
}
259
}
260
}
261
262
SetValueIsValid(false);
263
m_error = Status::FromErrorString("no register context");
264
return false;
265
}
266
267
bool ValueObjectRegister::SetValueFromCString(const char *value_str,
268
Status &error) {
269
// The new value will be in the m_data. Copy that into our register value.
270
error =
271
m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
272
if (!error.Success())
273
return false;
274
275
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
276
error = Status::FromErrorString("unable to write back to register");
277
return false;
278
}
279
280
SetNeedsUpdate();
281
return true;
282
}
283
284
bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
285
error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
286
if (!error.Success())
287
return false;
288
289
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
290
error = Status::FromErrorString("unable to write back to register");
291
return false;
292
}
293
294
SetNeedsUpdate();
295
return true;
296
}
297
298
bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
299
if (UpdateValueIfNeeded(
300
false)) // make sure that you are up to date before returning anything
301
return m_reg_value.GetScalarValue(scalar);
302
return false;
303
}
304
305
void ValueObjectRegister::GetExpressionPath(Stream &s,
306
GetExpressionPathFormat epformat) {
307
s.Printf("$%s", m_reg_info.name);
308
}
309
310