1cfca06d7SDimitry Andric //===-- ValueObjectRegister.cpp -------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Core/ValueObjectRegister.h"
10f034231aSEd Maste
11f034231aSEd Maste #include "lldb/Core/Module.h"
1294994d37SDimitry Andric #include "lldb/Core/Value.h"
1314f1b3e8SDimitry Andric #include "lldb/Symbol/CompilerType.h"
1494994d37SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
15f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
16f034231aSEd Maste #include "lldb/Target/Process.h"
17f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
1894994d37SDimitry Andric #include "lldb/Target/StackFrame.h"
19f034231aSEd Maste #include "lldb/Target/Target.h"
2094994d37SDimitry Andric #include "lldb/Utility/DataExtractor.h"
21145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
22ead24645SDimitry Andric #include "lldb/Utility/Log.h"
2394994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
2494994d37SDimitry Andric #include "lldb/Utility/Status.h"
2594994d37SDimitry Andric #include "lldb/Utility/Stream.h"
2674a628f7SDimitry Andric
2794994d37SDimitry Andric #include "llvm/ADT/StringRef.h"
2874a628f7SDimitry Andric
29344a3780SDimitry Andric #include <cassert>
3094994d37SDimitry Andric #include <memory>
31e3b55780SDimitry Andric #include <optional>
3274a628f7SDimitry Andric
3374a628f7SDimitry Andric namespace lldb_private {
3474a628f7SDimitry Andric class ExecutionContextScope;
3574a628f7SDimitry Andric }
36f034231aSEd Maste
37f034231aSEd Maste using namespace lldb;
38f034231aSEd Maste using namespace lldb_private;
39f034231aSEd Maste
40f034231aSEd Maste #pragma mark ValueObjectRegisterSet
41f034231aSEd Maste
42f034231aSEd Maste ValueObjectSP
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)4314f1b3e8SDimitry Andric ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
4414f1b3e8SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
4514f1b3e8SDimitry Andric uint32_t set_idx) {
46cfca06d7SDimitry Andric auto manager_sp = ValueObjectManager::Create();
47cfca06d7SDimitry Andric return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
48cfca06d7SDimitry Andric set_idx))
49cfca06d7SDimitry Andric ->GetSP();
50f034231aSEd Maste }
51f034231aSEd Maste
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)5214f1b3e8SDimitry Andric ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53cfca06d7SDimitry Andric ValueObjectManager &manager,
5414f1b3e8SDimitry Andric lldb::RegisterContextSP ®_ctx,
5514f1b3e8SDimitry Andric uint32_t reg_set_idx)
56cfca06d7SDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
57cfca06d7SDimitry Andric m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
58f034231aSEd Maste assert(reg_ctx);
59f034231aSEd Maste m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
6014f1b3e8SDimitry Andric if (m_reg_set) {
61f034231aSEd Maste m_name.SetCString(m_reg_set->name);
62f034231aSEd Maste }
63f034231aSEd Maste }
64f034231aSEd Maste
65344a3780SDimitry Andric ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66f034231aSEd Maste
GetCompilerTypeImpl()6714f1b3e8SDimitry Andric CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68e81d9d49SDimitry Andric return CompilerType();
69f034231aSEd Maste }
70f034231aSEd Maste
GetTypeName()7114f1b3e8SDimitry Andric ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
7214f1b3e8SDimitry Andric
GetQualifiedTypeName()7314f1b3e8SDimitry Andric ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74f034231aSEd Maste return ConstString();
75f034231aSEd Maste }
76f034231aSEd Maste
77ac9a064cSDimitry Andric llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)78ac9a064cSDimitry Andric ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
79f034231aSEd Maste const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
8014f1b3e8SDimitry Andric if (reg_set) {
81e81d9d49SDimitry Andric auto reg_count = reg_set->num_registers;
82e81d9d49SDimitry Andric return reg_count <= max ? reg_count : max;
83e81d9d49SDimitry Andric }
84f034231aSEd Maste return 0;
85f034231aSEd Maste }
86f034231aSEd Maste
GetByteSize()87e3b55780SDimitry Andric std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
88f034231aSEd Maste
UpdateValue()8914f1b3e8SDimitry Andric bool ValueObjectRegisterSet::UpdateValue() {
90f034231aSEd Maste m_error.Clear();
91f034231aSEd Maste SetValueDidChange(false);
92f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
93f034231aSEd Maste StackFrame *frame = exe_ctx.GetFramePtr();
945f29bb8aSDimitry Andric if (frame == nullptr)
95f034231aSEd Maste m_reg_ctx_sp.reset();
9614f1b3e8SDimitry Andric else {
97f034231aSEd Maste m_reg_ctx_sp = frame->GetRegisterContext();
9814f1b3e8SDimitry Andric if (m_reg_ctx_sp) {
99f034231aSEd Maste const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
1005f29bb8aSDimitry Andric if (reg_set == nullptr)
101f034231aSEd Maste m_reg_ctx_sp.reset();
10214f1b3e8SDimitry Andric else if (m_reg_set != reg_set) {
103f034231aSEd Maste SetValueDidChange(true);
104f034231aSEd Maste m_name.SetCString(reg_set->name);
105f034231aSEd Maste }
106f034231aSEd Maste }
107f034231aSEd Maste }
10814f1b3e8SDimitry Andric if (m_reg_ctx_sp) {
109f034231aSEd Maste SetValueIsValid(true);
11014f1b3e8SDimitry Andric } else {
111f034231aSEd Maste SetValueIsValid(false);
112f034231aSEd Maste m_error.SetErrorToGenericError();
113f034231aSEd Maste m_children.Clear();
114f034231aSEd Maste }
115f034231aSEd Maste return m_error.Success();
116f034231aSEd Maste }
117f034231aSEd Maste
CreateChildAtIndex(size_t idx)118ac9a064cSDimitry Andric ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {
11914f1b3e8SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
120ac9a064cSDimitry Andric return new ValueObjectRegister(
121c0981da4SDimitry Andric *this, m_reg_ctx_sp,
122c0981da4SDimitry Andric m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
123f034231aSEd Maste }
124ac9a064cSDimitry Andric return nullptr;
125f034231aSEd Maste }
126f034231aSEd Maste
127f034231aSEd Maste lldb::ValueObjectSP
GetChildMemberWithName(llvm::StringRef name,bool can_create)1287fa27ce4SDimitry Andric ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
12914f1b3e8SDimitry Andric bool can_create) {
1305f29bb8aSDimitry Andric ValueObject *valobj = nullptr;
13114f1b3e8SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
1327fa27ce4SDimitry Andric const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
1335f29bb8aSDimitry Andric if (reg_info != nullptr)
134c0981da4SDimitry Andric valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
135f034231aSEd Maste }
136f034231aSEd Maste if (valobj)
137f034231aSEd Maste return valobj->GetSP();
138f034231aSEd Maste else
139f034231aSEd Maste return ValueObjectSP();
140f034231aSEd Maste }
141f034231aSEd Maste
GetIndexOfChildWithName(llvm::StringRef name)1427fa27ce4SDimitry Andric size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
14314f1b3e8SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
1447fa27ce4SDimitry Andric const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
1455f29bb8aSDimitry Andric if (reg_info != nullptr)
146f034231aSEd Maste return reg_info->kinds[eRegisterKindLLDB];
147f034231aSEd Maste }
148f034231aSEd Maste return UINT32_MAX;
149f034231aSEd Maste }
150f034231aSEd Maste
151f034231aSEd Maste #pragma mark -
152f034231aSEd Maste #pragma mark ValueObjectRegister
153f034231aSEd Maste
ConstructObject(const RegisterInfo * reg_info)154c0981da4SDimitry Andric void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
15514f1b3e8SDimitry Andric if (reg_info) {
156f034231aSEd Maste m_reg_info = *reg_info;
157f034231aSEd Maste if (reg_info->name)
158f034231aSEd Maste m_name.SetCString(reg_info->name);
159f034231aSEd Maste else if (reg_info->alt_name)
160f034231aSEd Maste m_name.SetCString(reg_info->alt_name);
161f034231aSEd Maste }
162f034231aSEd Maste }
163f034231aSEd Maste
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)16414f1b3e8SDimitry Andric ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
16514f1b3e8SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
166c0981da4SDimitry Andric const RegisterInfo *reg_info)
16714f1b3e8SDimitry Andric : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
16814f1b3e8SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() {
169f034231aSEd Maste assert(reg_ctx_sp.get());
170c0981da4SDimitry Andric ConstructObject(reg_info);
171f034231aSEd Maste }
172f034231aSEd Maste
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)17314f1b3e8SDimitry Andric ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
17414f1b3e8SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
175c0981da4SDimitry Andric const RegisterInfo *reg_info) {
176cfca06d7SDimitry Andric auto manager_sp = ValueObjectManager::Create();
177c0981da4SDimitry Andric return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
178cfca06d7SDimitry Andric ->GetSP();
179f034231aSEd Maste }
180f034231aSEd Maste
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)18114f1b3e8SDimitry Andric ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
182cfca06d7SDimitry Andric ValueObjectManager &manager,
18314f1b3e8SDimitry Andric lldb::RegisterContextSP ®_ctx,
184c0981da4SDimitry Andric const RegisterInfo *reg_info)
185cfca06d7SDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
18614f1b3e8SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() {
187f034231aSEd Maste assert(reg_ctx);
188c0981da4SDimitry Andric ConstructObject(reg_info);
189f034231aSEd Maste }
190f034231aSEd Maste
191344a3780SDimitry Andric ValueObjectRegister::~ValueObjectRegister() = default;
192f034231aSEd Maste
GetCompilerTypeImpl()19314f1b3e8SDimitry Andric CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
19414f1b3e8SDimitry Andric if (!m_compiler_type.IsValid()) {
195f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
196ead24645SDimitry Andric if (auto *target = exe_ctx.GetTargetPtr()) {
197ead24645SDimitry Andric if (auto *exe_module = target->GetExecutableModulePointer()) {
198ead24645SDimitry Andric auto type_system_or_err =
19914f1b3e8SDimitry Andric exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
200ead24645SDimitry Andric if (auto err = type_system_or_err.takeError()) {
201145449b1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
2027fa27ce4SDimitry Andric "Unable to get CompilerType from TypeSystem: {0}");
203ead24645SDimitry Andric } else {
204e3b55780SDimitry Andric if (auto ts = *type_system_or_err)
205e3b55780SDimitry Andric m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
20614f1b3e8SDimitry Andric m_reg_info.encoding, m_reg_info.byte_size * 8);
207f034231aSEd Maste }
208f034231aSEd Maste }
209f034231aSEd Maste }
210ead24645SDimitry Andric }
211e81d9d49SDimitry Andric return m_compiler_type;
212f034231aSEd Maste }
213f034231aSEd Maste
GetTypeName()21414f1b3e8SDimitry Andric ConstString ValueObjectRegister::GetTypeName() {
215f034231aSEd Maste if (m_type_name.IsEmpty())
216cfca06d7SDimitry Andric m_type_name = GetCompilerType().GetTypeName();
217f034231aSEd Maste return m_type_name;
218f034231aSEd Maste }
219f034231aSEd Maste
220ac9a064cSDimitry Andric llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)221ac9a064cSDimitry Andric ValueObjectRegister::CalculateNumChildren(uint32_t max) {
22294994d37SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
22394994d37SDimitry Andric auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
224ac9a064cSDimitry Andric if (!children_count)
225ac9a064cSDimitry Andric return children_count;
226ac9a064cSDimitry Andric return *children_count <= max ? *children_count : max;
227f034231aSEd Maste }
228f034231aSEd Maste
GetByteSize()229e3b55780SDimitry Andric std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
230b60736ecSDimitry Andric return m_reg_info.byte_size;
231b60736ecSDimitry Andric }
232f034231aSEd Maste
UpdateValue()23314f1b3e8SDimitry Andric bool ValueObjectRegister::UpdateValue() {
234f034231aSEd Maste m_error.Clear();
235f034231aSEd Maste ExecutionContext exe_ctx(GetExecutionContextRef());
236f034231aSEd Maste StackFrame *frame = exe_ctx.GetFramePtr();
2375f29bb8aSDimitry Andric if (frame == nullptr) {
238f034231aSEd Maste m_reg_ctx_sp.reset();
239f034231aSEd Maste m_reg_value.Clear();
240f034231aSEd Maste }
241f034231aSEd Maste
24214f1b3e8SDimitry Andric if (m_reg_ctx_sp) {
24314f1b3e8SDimitry Andric RegisterValue m_old_reg_value(m_reg_value);
24414f1b3e8SDimitry Andric if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
24514f1b3e8SDimitry Andric if (m_reg_value.GetData(m_data)) {
246f034231aSEd Maste Process *process = exe_ctx.GetProcessPtr();
247f034231aSEd Maste if (process)
248f034231aSEd Maste m_data.SetAddressByteSize(process->GetAddressByteSize());
249344a3780SDimitry Andric m_value.SetContext(Value::ContextType::RegisterInfo,
25014f1b3e8SDimitry Andric (void *)&m_reg_info);
251344a3780SDimitry Andric m_value.SetValueType(Value::ValueType::HostAddress);
252f034231aSEd Maste m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
253f034231aSEd Maste SetValueIsValid(true);
25414f1b3e8SDimitry Andric SetValueDidChange(!(m_old_reg_value == m_reg_value));
255f034231aSEd Maste return true;
256f034231aSEd Maste }
257f034231aSEd Maste }
258f034231aSEd Maste }
259f034231aSEd Maste
260f034231aSEd Maste SetValueIsValid(false);
261f034231aSEd Maste m_error.SetErrorToGenericError();
262f034231aSEd Maste return false;
263f034231aSEd Maste }
264f034231aSEd Maste
SetValueFromCString(const char * value_str,Status & error)26514f1b3e8SDimitry Andric bool ValueObjectRegister::SetValueFromCString(const char *value_str,
266b76161e4SDimitry Andric Status &error) {
267f034231aSEd Maste // The new value will be in the m_data. Copy that into our register value.
26814f1b3e8SDimitry Andric error =
26914f1b3e8SDimitry Andric m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
270145449b1SDimitry Andric if (!error.Success())
271145449b1SDimitry Andric return false;
272145449b1SDimitry Andric
273145449b1SDimitry Andric if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
274145449b1SDimitry Andric error.SetErrorString("unable to write back to register");
275145449b1SDimitry Andric return false;
276145449b1SDimitry Andric }
277145449b1SDimitry Andric
278f034231aSEd Maste SetNeedsUpdate();
279f034231aSEd Maste return true;
280f034231aSEd Maste }
281f034231aSEd Maste
SetData(DataExtractor & data,Status & error)282b76161e4SDimitry Andric bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
283e3b55780SDimitry Andric error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
284145449b1SDimitry Andric if (!error.Success())
285145449b1SDimitry Andric return false;
286145449b1SDimitry Andric
287145449b1SDimitry Andric if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
288145449b1SDimitry Andric error.SetErrorString("unable to write back to register");
289145449b1SDimitry Andric return false;
290145449b1SDimitry Andric }
291145449b1SDimitry Andric
292f034231aSEd Maste SetNeedsUpdate();
293f034231aSEd Maste return true;
294f034231aSEd Maste }
295f034231aSEd Maste
ResolveValue(Scalar & scalar)29614f1b3e8SDimitry Andric bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
29714f1b3e8SDimitry Andric if (UpdateValueIfNeeded(
29814f1b3e8SDimitry Andric false)) // make sure that you are up to date before returning anything
299f034231aSEd Maste return m_reg_value.GetScalarValue(scalar);
300f034231aSEd Maste return false;
301f034231aSEd Maste }
302f034231aSEd Maste
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)30314f1b3e8SDimitry Andric void ValueObjectRegister::GetExpressionPath(Stream &s,
30414f1b3e8SDimitry Andric GetExpressionPathFormat epformat) {
305f034231aSEd Maste s.Printf("$%s", m_reg_info.name);
306f034231aSEd Maste }
307