xref: /src/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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