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/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
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)43 ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
44 lldb::RegisterContextSP ®_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
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)52 ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53 ValueObjectManager &manager,
54 lldb::RegisterContextSP ®_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
GetCompilerTypeImpl()67 CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68 return CompilerType();
69 }
70
GetTypeName()71 ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72
GetQualifiedTypeName()73 ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74 return ConstString();
75 }
76
77 llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)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
GetByteSize()87 std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
88
UpdateValue()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.SetErrorToGenericError();
113 m_children.Clear();
114 }
115 return m_error.Success();
116 }
117
CreateChildAtIndex(size_t idx)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
GetChildMemberWithName(llvm::StringRef name,bool can_create)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
GetIndexOfChildWithName(llvm::StringRef name)142 size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
143 if (m_reg_ctx_sp && m_reg_set) {
144 const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
145 if (reg_info != nullptr)
146 return reg_info->kinds[eRegisterKindLLDB];
147 }
148 return UINT32_MAX;
149 }
150
151 #pragma mark -
152 #pragma mark ValueObjectRegister
153
ConstructObject(const RegisterInfo * reg_info)154 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
155 if (reg_info) {
156 m_reg_info = *reg_info;
157 if (reg_info->name)
158 m_name.SetCString(reg_info->name);
159 else if (reg_info->alt_name)
160 m_name.SetCString(reg_info->alt_name);
161 }
162 }
163
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)164 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
165 lldb::RegisterContextSP ®_ctx_sp,
166 const RegisterInfo *reg_info)
167 : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
168 m_reg_value(), m_type_name(), m_compiler_type() {
169 assert(reg_ctx_sp.get());
170 ConstructObject(reg_info);
171 }
172
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)173 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
174 lldb::RegisterContextSP ®_ctx_sp,
175 const RegisterInfo *reg_info) {
176 auto manager_sp = ValueObjectManager::Create();
177 return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
178 ->GetSP();
179 }
180
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)181 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
182 ValueObjectManager &manager,
183 lldb::RegisterContextSP ®_ctx,
184 const RegisterInfo *reg_info)
185 : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
186 m_reg_value(), m_type_name(), m_compiler_type() {
187 assert(reg_ctx);
188 ConstructObject(reg_info);
189 }
190
191 ValueObjectRegister::~ValueObjectRegister() = default;
192
GetCompilerTypeImpl()193 CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
194 if (!m_compiler_type.IsValid()) {
195 ExecutionContext exe_ctx(GetExecutionContextRef());
196 if (auto *target = exe_ctx.GetTargetPtr()) {
197 if (auto *exe_module = target->GetExecutableModulePointer()) {
198 auto type_system_or_err =
199 exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
200 if (auto err = type_system_or_err.takeError()) {
201 LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
202 "Unable to get CompilerType from TypeSystem: {0}");
203 } else {
204 if (auto ts = *type_system_or_err)
205 m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
206 m_reg_info.encoding, m_reg_info.byte_size * 8);
207 }
208 }
209 }
210 }
211 return m_compiler_type;
212 }
213
GetTypeName()214 ConstString ValueObjectRegister::GetTypeName() {
215 if (m_type_name.IsEmpty())
216 m_type_name = GetCompilerType().GetTypeName();
217 return m_type_name;
218 }
219
220 llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)221 ValueObjectRegister::CalculateNumChildren(uint32_t max) {
222 ExecutionContext exe_ctx(GetExecutionContextRef());
223 auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
224 if (!children_count)
225 return children_count;
226 return *children_count <= max ? *children_count : max;
227 }
228
GetByteSize()229 std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
230 return m_reg_info.byte_size;
231 }
232
UpdateValue()233 bool ValueObjectRegister::UpdateValue() {
234 m_error.Clear();
235 ExecutionContext exe_ctx(GetExecutionContextRef());
236 StackFrame *frame = exe_ctx.GetFramePtr();
237 if (frame == nullptr) {
238 m_reg_ctx_sp.reset();
239 m_reg_value.Clear();
240 }
241
242 if (m_reg_ctx_sp) {
243 RegisterValue m_old_reg_value(m_reg_value);
244 if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
245 if (m_reg_value.GetData(m_data)) {
246 Process *process = exe_ctx.GetProcessPtr();
247 if (process)
248 m_data.SetAddressByteSize(process->GetAddressByteSize());
249 m_value.SetContext(Value::ContextType::RegisterInfo,
250 (void *)&m_reg_info);
251 m_value.SetValueType(Value::ValueType::HostAddress);
252 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
253 SetValueIsValid(true);
254 SetValueDidChange(!(m_old_reg_value == m_reg_value));
255 return true;
256 }
257 }
258 }
259
260 SetValueIsValid(false);
261 m_error.SetErrorToGenericError();
262 return false;
263 }
264
SetValueFromCString(const char * value_str,Status & error)265 bool ValueObjectRegister::SetValueFromCString(const char *value_str,
266 Status &error) {
267 // The new value will be in the m_data. Copy that into our register value.
268 error =
269 m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
270 if (!error.Success())
271 return false;
272
273 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
274 error.SetErrorString("unable to write back to register");
275 return false;
276 }
277
278 SetNeedsUpdate();
279 return true;
280 }
281
SetData(DataExtractor & data,Status & error)282 bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
283 error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
284 if (!error.Success())
285 return false;
286
287 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
288 error.SetErrorString("unable to write back to register");
289 return false;
290 }
291
292 SetNeedsUpdate();
293 return true;
294 }
295
ResolveValue(Scalar & scalar)296 bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
297 if (UpdateValueIfNeeded(
298 false)) // make sure that you are up to date before returning anything
299 return m_reg_value.GetScalarValue(scalar);
300 return false;
301 }
302
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)303 void ValueObjectRegister::GetExpressionPath(Stream &s,
304 GetExpressionPathFormat epformat) {
305 s.Printf("$%s", m_reg_info.name);
306 }
307