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
32 namespace lldb_private {
33 class ExecutionContextScope;
34 }
35
36 using namespace lldb;
37 using namespace lldb_private;
38
39 #pragma mark ValueObjectRegisterSet
40
41 ValueObjectSP
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)42 ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
43 lldb::RegisterContextSP ®_ctx_sp,
44 uint32_t set_idx) {
45 auto manager_sp = ValueObjectManager::Create();
46 return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
47 set_idx))
48 ->GetSP();
49 }
50
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)51 ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
52 ValueObjectManager &manager,
53 lldb::RegisterContextSP ®_ctx,
54 uint32_t reg_set_idx)
55 : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
56 m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
57 assert(reg_ctx);
58 m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
59 if (m_reg_set) {
60 m_name.SetCString(m_reg_set->name);
61 }
62 }
63
64 ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
65
GetCompilerTypeImpl()66 CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
67 return CompilerType();
68 }
69
GetTypeName()70 ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
71
GetQualifiedTypeName()72 ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
73 return ConstString();
74 }
75
CalculateNumChildren(uint32_t max)76 size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
77 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
78 if (reg_set) {
79 auto reg_count = reg_set->num_registers;
80 return reg_count <= max ? reg_count : max;
81 }
82 return 0;
83 }
84
GetByteSize()85 llvm::Optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
86
UpdateValue()87 bool ValueObjectRegisterSet::UpdateValue() {
88 m_error.Clear();
89 SetValueDidChange(false);
90 ExecutionContext exe_ctx(GetExecutionContextRef());
91 StackFrame *frame = exe_ctx.GetFramePtr();
92 if (frame == nullptr)
93 m_reg_ctx_sp.reset();
94 else {
95 m_reg_ctx_sp = frame->GetRegisterContext();
96 if (m_reg_ctx_sp) {
97 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
98 if (reg_set == nullptr)
99 m_reg_ctx_sp.reset();
100 else if (m_reg_set != reg_set) {
101 SetValueDidChange(true);
102 m_name.SetCString(reg_set->name);
103 }
104 }
105 }
106 if (m_reg_ctx_sp) {
107 SetValueIsValid(true);
108 } else {
109 SetValueIsValid(false);
110 m_error.SetErrorToGenericError();
111 m_children.Clear();
112 }
113 return m_error.Success();
114 }
115
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)116 ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
117 size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
118 ValueObject *valobj = nullptr;
119 if (m_reg_ctx_sp && m_reg_set) {
120 const size_t num_children = GetNumChildren();
121 if (idx < num_children)
122 valobj = new ValueObjectRegister(
123 *this, m_reg_ctx_sp,
124 m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
125 }
126 return valobj;
127 }
128
129 lldb::ValueObjectSP
GetChildMemberWithName(ConstString name,bool can_create)130 ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
131 bool can_create) {
132 ValueObject *valobj = nullptr;
133 if (m_reg_ctx_sp && m_reg_set) {
134 const RegisterInfo *reg_info =
135 m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
136 if (reg_info != nullptr)
137 valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
138 }
139 if (valobj)
140 return valobj->GetSP();
141 else
142 return ValueObjectSP();
143 }
144
145 size_t
GetIndexOfChildWithName(ConstString name)146 ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
147 if (m_reg_ctx_sp && m_reg_set) {
148 const RegisterInfo *reg_info =
149 m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
150 if (reg_info != nullptr)
151 return reg_info->kinds[eRegisterKindLLDB];
152 }
153 return UINT32_MAX;
154 }
155
156 #pragma mark -
157 #pragma mark ValueObjectRegister
158
ConstructObject(const RegisterInfo * reg_info)159 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
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
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)169 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
170 lldb::RegisterContextSP ®_ctx_sp,
171 const RegisterInfo *reg_info)
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_info);
176 }
177
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)178 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
179 lldb::RegisterContextSP ®_ctx_sp,
180 const RegisterInfo *reg_info) {
181 auto manager_sp = ValueObjectManager::Create();
182 return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
183 ->GetSP();
184 }
185
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)186 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
187 ValueObjectManager &manager,
188 lldb::RegisterContextSP ®_ctx,
189 const RegisterInfo *reg_info)
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_info);
194 }
195
196 ValueObjectRegister::~ValueObjectRegister() = default;
197
GetCompilerTypeImpl()198 CompilerType 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(GetLog(LLDBLog::Types), std::move(err),
207 "Unable to get CompilerType from TypeSystem");
208 } else {
209 m_compiler_type =
210 type_system_or_err->GetBuiltinTypeForEncodingAndBitSize(
211 m_reg_info.encoding, m_reg_info.byte_size * 8);
212 }
213 }
214 }
215 }
216 return m_compiler_type;
217 }
218
GetTypeName()219 ConstString ValueObjectRegister::GetTypeName() {
220 if (m_type_name.IsEmpty())
221 m_type_name = GetCompilerType().GetTypeName();
222 return m_type_name;
223 }
224
CalculateNumChildren(uint32_t max)225 size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
226 ExecutionContext exe_ctx(GetExecutionContextRef());
227 auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
228 return children_count <= max ? children_count : max;
229 }
230
GetByteSize()231 llvm::Optional<uint64_t> ValueObjectRegister::GetByteSize() {
232 return m_reg_info.byte_size;
233 }
234
UpdateValue()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.SetErrorToGenericError();
264 return false;
265 }
266
SetValueFromCString(const char * value_str,Status & error)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.SetErrorString("unable to write back to register");
277 return false;
278 }
279
280 SetNeedsUpdate();
281 return true;
282 }
283
SetData(DataExtractor & data,Status & error)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.SetErrorString("unable to write back to register");
291 return false;
292 }
293
294 SetNeedsUpdate();
295 return true;
296 }
297
ResolveValue(Scalar & scalar)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
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)305 void ValueObjectRegister::GetExpressionPath(Stream &s,
306 GetExpressionPathFormat epformat) {
307 s.Printf("$%s", m_reg_info.name);
308 }
309