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