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
CalculateNumChildren(uint32_t max)77 size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
78 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
79 if (reg_set) {
80 auto reg_count = reg_set->num_registers;
81 return reg_count <= max ? reg_count : max;
82 }
83 return 0;
84 }
85
GetByteSize()86 std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
87
UpdateValue()88 bool ValueObjectRegisterSet::UpdateValue() {
89 m_error.Clear();
90 SetValueDidChange(false);
91 ExecutionContext exe_ctx(GetExecutionContextRef());
92 StackFrame *frame = exe_ctx.GetFramePtr();
93 if (frame == nullptr)
94 m_reg_ctx_sp.reset();
95 else {
96 m_reg_ctx_sp = frame->GetRegisterContext();
97 if (m_reg_ctx_sp) {
98 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
99 if (reg_set == nullptr)
100 m_reg_ctx_sp.reset();
101 else if (m_reg_set != reg_set) {
102 SetValueDidChange(true);
103 m_name.SetCString(reg_set->name);
104 }
105 }
106 }
107 if (m_reg_ctx_sp) {
108 SetValueIsValid(true);
109 } else {
110 SetValueIsValid(false);
111 m_error.SetErrorToGenericError();
112 m_children.Clear();
113 }
114 return m_error.Success();
115 }
116
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)117 ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
118 size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
119 ValueObject *valobj = nullptr;
120 if (m_reg_ctx_sp && m_reg_set) {
121 const size_t num_children = GetNumChildren();
122 if (idx < num_children)
123 valobj = new ValueObjectRegister(
124 *this, m_reg_ctx_sp,
125 m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
126 }
127 return valobj;
128 }
129
130 lldb::ValueObjectSP
GetChildMemberWithName(ConstString name,bool can_create)131 ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
132 bool can_create) {
133 ValueObject *valobj = nullptr;
134 if (m_reg_ctx_sp && m_reg_set) {
135 const RegisterInfo *reg_info =
136 m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
137 if (reg_info != nullptr)
138 valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
139 }
140 if (valobj)
141 return valobj->GetSP();
142 else
143 return ValueObjectSP();
144 }
145
146 size_t
GetIndexOfChildWithName(ConstString name)147 ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
148 if (m_reg_ctx_sp && m_reg_set) {
149 const RegisterInfo *reg_info =
150 m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
151 if (reg_info != nullptr)
152 return reg_info->kinds[eRegisterKindLLDB];
153 }
154 return UINT32_MAX;
155 }
156
157 #pragma mark -
158 #pragma mark ValueObjectRegister
159
ConstructObject(const RegisterInfo * reg_info)160 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
161 if (reg_info) {
162 m_reg_info = *reg_info;
163 if (reg_info->name)
164 m_name.SetCString(reg_info->name);
165 else if (reg_info->alt_name)
166 m_name.SetCString(reg_info->alt_name);
167 }
168 }
169
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)170 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
171 lldb::RegisterContextSP ®_ctx_sp,
172 const RegisterInfo *reg_info)
173 : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
174 m_reg_value(), m_type_name(), m_compiler_type() {
175 assert(reg_ctx_sp.get());
176 ConstructObject(reg_info);
177 }
178
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)179 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
180 lldb::RegisterContextSP ®_ctx_sp,
181 const RegisterInfo *reg_info) {
182 auto manager_sp = ValueObjectManager::Create();
183 return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
184 ->GetSP();
185 }
186
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)187 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
188 ValueObjectManager &manager,
189 lldb::RegisterContextSP ®_ctx,
190 const RegisterInfo *reg_info)
191 : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
192 m_reg_value(), m_type_name(), m_compiler_type() {
193 assert(reg_ctx);
194 ConstructObject(reg_info);
195 }
196
197 ValueObjectRegister::~ValueObjectRegister() = default;
198
GetCompilerTypeImpl()199 CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
200 if (!m_compiler_type.IsValid()) {
201 ExecutionContext exe_ctx(GetExecutionContextRef());
202 if (auto *target = exe_ctx.GetTargetPtr()) {
203 if (auto *exe_module = target->GetExecutableModulePointer()) {
204 auto type_system_or_err =
205 exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
206 if (auto err = type_system_or_err.takeError()) {
207 LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
208 "Unable to get CompilerType from TypeSystem");
209 } else {
210 if (auto ts = *type_system_or_err)
211 m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
212 m_reg_info.encoding, m_reg_info.byte_size * 8);
213 }
214 }
215 }
216 }
217 return m_compiler_type;
218 }
219
GetTypeName()220 ConstString ValueObjectRegister::GetTypeName() {
221 if (m_type_name.IsEmpty())
222 m_type_name = GetCompilerType().GetTypeName();
223 return m_type_name;
224 }
225
CalculateNumChildren(uint32_t max)226 size_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
GetByteSize()232 std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
233 return m_reg_info.byte_size;
234 }
235
UpdateValue()236 bool 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
SetValueFromCString(const char * value_str,Status & error)268 bool 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 return false;
275
276 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
277 error.SetErrorString("unable to write back to register");
278 return false;
279 }
280
281 SetNeedsUpdate();
282 return true;
283 }
284
SetData(DataExtractor & data,Status & error)285 bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
286 error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
287 if (!error.Success())
288 return false;
289
290 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
291 error.SetErrorString("unable to write back to register");
292 return false;
293 }
294
295 SetNeedsUpdate();
296 return true;
297 }
298
ResolveValue(Scalar & scalar)299 bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
300 if (UpdateValueIfNeeded(
301 false)) // make sure that you are up to date before returning anything
302 return m_reg_value.GetScalarValue(scalar);
303 return false;
304 }
305
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)306 void ValueObjectRegister::GetExpressionPath(Stream &s,
307 GetExpressionPathFormat epformat) {
308 s.Printf("$%s", m_reg_info.name);
309 }
310