1 //===-- ValueObjectRegister.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/ValueObject/ValueObjectRegister.h"
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"
27 #include "llvm/ADT/StringRef.h"
33 namespace lldb_private
{
34 class ExecutionContextScope
;
38 using namespace lldb_private
;
40 #pragma mark ValueObjectRegisterSet
43 ValueObjectRegisterSet::Create(ExecutionContextScope
*exe_scope
,
44 lldb::RegisterContextSP
®_ctx_sp
,
46 auto manager_sp
= ValueObjectManager::Create();
47 return (new ValueObjectRegisterSet(exe_scope
, *manager_sp
, reg_ctx_sp
,
52 ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope
*exe_scope
,
53 ValueObjectManager
&manager
,
54 lldb::RegisterContextSP
®_ctx
,
56 : ValueObject(exe_scope
, manager
), m_reg_ctx_sp(reg_ctx
),
57 m_reg_set(nullptr), m_reg_set_idx(reg_set_idx
) {
59 m_reg_set
= reg_ctx
->GetRegisterSet(m_reg_set_idx
);
61 m_name
.SetCString(m_reg_set
->name
);
65 ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
67 CompilerType
ValueObjectRegisterSet::GetCompilerTypeImpl() {
68 return CompilerType();
71 ConstString
ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
73 ConstString
ValueObjectRegisterSet::GetQualifiedTypeName() {
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
);
81 auto reg_count
= reg_set
->num_registers
;
82 return reg_count
<= max
? reg_count
: max
;
87 std::optional
<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
89 bool ValueObjectRegisterSet::UpdateValue() {
91 SetValueDidChange(false);
92 ExecutionContext
exe_ctx(GetExecutionContextRef());
93 StackFrame
*frame
= exe_ctx
.GetFramePtr();
97 m_reg_ctx_sp
= frame
->GetRegisterContext();
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
);
109 SetValueIsValid(true);
111 SetValueIsValid(false);
112 m_error
= Status::FromErrorString("no register context");
115 return m_error
.Success();
118 ValueObject
*ValueObjectRegisterSet::CreateChildAtIndex(size_t idx
) {
119 if (m_reg_ctx_sp
&& m_reg_set
) {
120 return new ValueObjectRegister(
122 m_reg_ctx_sp
->GetRegisterInfoAtIndex(m_reg_set
->registers
[idx
]));
128 ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name
,
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
);
137 return valobj
->GetSP();
139 return ValueObjectSP();
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
];
152 #pragma mark ValueObjectRegister
154 void ValueObjectRegister::ConstructObject(const RegisterInfo
*reg_info
) {
156 m_reg_info
= *reg_info
;
158 m_name
.SetCString(reg_info
->name
);
159 else if (reg_info
->alt_name
)
160 m_name
.SetCString(reg_info
->alt_name
);
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
);
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
))
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() {
188 ConstructObject(reg_info
);
191 ValueObjectRegister::~ValueObjectRegister() = default;
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}");
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);
211 return m_compiler_type
;
214 ConstString
ValueObjectRegister::GetTypeName() {
215 if (m_type_name
.IsEmpty())
216 m_type_name
= GetCompilerType().GetTypeName();
220 llvm::Expected
<uint32_t>
221 ValueObjectRegister::CalculateNumChildren(uint32_t max
) {
222 ExecutionContext
exe_ctx(GetExecutionContextRef());
223 auto children_count
= GetCompilerType().GetNumChildren(true, &exe_ctx
);
225 return children_count
;
226 return *children_count
<= max
? *children_count
: max
;
229 std::optional
<uint64_t> ValueObjectRegister::GetByteSize() {
230 return m_reg_info
.byte_size
;
233 bool ValueObjectRegister::UpdateValue() {
235 ExecutionContext
exe_ctx(GetExecutionContextRef());
236 StackFrame
*frame
= exe_ctx
.GetFramePtr();
237 if (frame
== nullptr) {
238 m_reg_ctx_sp
.reset();
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();
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
));
260 SetValueIsValid(false);
261 m_error
= Status::FromErrorString("no register context");
265 bool ValueObjectRegister::SetValueFromCString(const char *value_str
,
267 // The new value will be in the m_data. Copy that into our register value.
269 m_reg_value
.SetValueFromString(&m_reg_info
, llvm::StringRef(value_str
));
270 if (!error
.Success())
273 if (!m_reg_ctx_sp
->WriteRegister(&m_reg_info
, m_reg_value
)) {
274 error
= Status::FromErrorString("unable to write back to register");
282 bool ValueObjectRegister::SetData(DataExtractor
&data
, Status
&error
) {
283 error
= m_reg_value
.SetValueFromData(m_reg_info
, data
, 0, false);
284 if (!error
.Success())
287 if (!m_reg_ctx_sp
->WriteRegister(&m_reg_info
, m_reg_value
)) {
288 error
= Status::FromErrorString("unable to write back to register");
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
);
303 void ValueObjectRegister::GetExpressionPath(Stream
&s
,
304 GetExpressionPathFormat epformat
) {
305 s
.Printf("$%s", m_reg_info
.name
);