xref: /openbsd-src/gnu/llvm/lldb/source/Core/ValueObjectRegister.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- ValueObjectRegister.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/ValueObjectRegister.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/Value.h"
13061da546Spatrick #include "lldb/Symbol/CompilerType.h"
14061da546Spatrick #include "lldb/Symbol/TypeSystem.h"
15061da546Spatrick #include "lldb/Target/ExecutionContext.h"
16061da546Spatrick #include "lldb/Target/Process.h"
17061da546Spatrick #include "lldb/Target/RegisterContext.h"
18061da546Spatrick #include "lldb/Target/StackFrame.h"
19061da546Spatrick #include "lldb/Target/Target.h"
20061da546Spatrick #include "lldb/Utility/DataExtractor.h"
21*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
22061da546Spatrick #include "lldb/Utility/Log.h"
23061da546Spatrick #include "lldb/Utility/Scalar.h"
24061da546Spatrick #include "lldb/Utility/Status.h"
25061da546Spatrick #include "lldb/Utility/Stream.h"
26061da546Spatrick 
27061da546Spatrick #include "llvm/ADT/StringRef.h"
28061da546Spatrick 
29be691f3bSpatrick #include <cassert>
30061da546Spatrick #include <memory>
31*f6aab3d8Srobert #include <optional>
32061da546Spatrick 
33061da546Spatrick namespace lldb_private {
34061da546Spatrick class ExecutionContextScope;
35061da546Spatrick }
36061da546Spatrick 
37061da546Spatrick using namespace lldb;
38061da546Spatrick using namespace lldb_private;
39061da546Spatrick 
40061da546Spatrick #pragma mark ValueObjectRegisterSet
41061da546Spatrick 
42061da546Spatrick ValueObjectSP
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)43061da546Spatrick ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
44061da546Spatrick                                lldb::RegisterContextSP &reg_ctx_sp,
45061da546Spatrick                                uint32_t set_idx) {
46dda28197Spatrick   auto manager_sp = ValueObjectManager::Create();
47dda28197Spatrick   return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
48dda28197Spatrick                                      set_idx))
49dda28197Spatrick       ->GetSP();
50061da546Spatrick }
51061da546Spatrick 
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)52061da546Spatrick ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53dda28197Spatrick                                                ValueObjectManager &manager,
54061da546Spatrick                                                lldb::RegisterContextSP &reg_ctx,
55061da546Spatrick                                                uint32_t reg_set_idx)
56dda28197Spatrick     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
57dda28197Spatrick       m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
58061da546Spatrick   assert(reg_ctx);
59061da546Spatrick   m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
60061da546Spatrick   if (m_reg_set) {
61061da546Spatrick     m_name.SetCString(m_reg_set->name);
62061da546Spatrick   }
63061da546Spatrick }
64061da546Spatrick 
65be691f3bSpatrick ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66061da546Spatrick 
GetCompilerTypeImpl()67061da546Spatrick CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68061da546Spatrick   return CompilerType();
69061da546Spatrick }
70061da546Spatrick 
GetTypeName()71061da546Spatrick ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72061da546Spatrick 
GetQualifiedTypeName()73061da546Spatrick ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74061da546Spatrick   return ConstString();
75061da546Spatrick }
76061da546Spatrick 
CalculateNumChildren(uint32_t max)77061da546Spatrick size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
78061da546Spatrick   const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
79061da546Spatrick   if (reg_set) {
80061da546Spatrick     auto reg_count = reg_set->num_registers;
81061da546Spatrick     return reg_count <= max ? reg_count : max;
82061da546Spatrick   }
83061da546Spatrick   return 0;
84061da546Spatrick }
85061da546Spatrick 
GetByteSize()86*f6aab3d8Srobert std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
87061da546Spatrick 
UpdateValue()88061da546Spatrick bool ValueObjectRegisterSet::UpdateValue() {
89061da546Spatrick   m_error.Clear();
90061da546Spatrick   SetValueDidChange(false);
91061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
92061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
93061da546Spatrick   if (frame == nullptr)
94061da546Spatrick     m_reg_ctx_sp.reset();
95061da546Spatrick   else {
96061da546Spatrick     m_reg_ctx_sp = frame->GetRegisterContext();
97061da546Spatrick     if (m_reg_ctx_sp) {
98061da546Spatrick       const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
99061da546Spatrick       if (reg_set == nullptr)
100061da546Spatrick         m_reg_ctx_sp.reset();
101061da546Spatrick       else if (m_reg_set != reg_set) {
102061da546Spatrick         SetValueDidChange(true);
103061da546Spatrick         m_name.SetCString(reg_set->name);
104061da546Spatrick       }
105061da546Spatrick     }
106061da546Spatrick   }
107061da546Spatrick   if (m_reg_ctx_sp) {
108061da546Spatrick     SetValueIsValid(true);
109061da546Spatrick   } else {
110061da546Spatrick     SetValueIsValid(false);
111061da546Spatrick     m_error.SetErrorToGenericError();
112061da546Spatrick     m_children.Clear();
113061da546Spatrick   }
114061da546Spatrick   return m_error.Success();
115061da546Spatrick }
116061da546Spatrick 
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)117061da546Spatrick ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
118061da546Spatrick     size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
119061da546Spatrick   ValueObject *valobj = nullptr;
120061da546Spatrick   if (m_reg_ctx_sp && m_reg_set) {
121061da546Spatrick     const size_t num_children = GetNumChildren();
122061da546Spatrick     if (idx < num_children)
123*f6aab3d8Srobert       valobj = new ValueObjectRegister(
124*f6aab3d8Srobert           *this, m_reg_ctx_sp,
125*f6aab3d8Srobert           m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
126061da546Spatrick   }
127061da546Spatrick   return valobj;
128061da546Spatrick }
129061da546Spatrick 
130061da546Spatrick lldb::ValueObjectSP
GetChildMemberWithName(ConstString name,bool can_create)131061da546Spatrick ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
132061da546Spatrick                                                bool can_create) {
133061da546Spatrick   ValueObject *valobj = nullptr;
134061da546Spatrick   if (m_reg_ctx_sp && m_reg_set) {
135061da546Spatrick     const RegisterInfo *reg_info =
136dda28197Spatrick         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
137061da546Spatrick     if (reg_info != nullptr)
138*f6aab3d8Srobert       valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
139061da546Spatrick   }
140061da546Spatrick   if (valobj)
141061da546Spatrick     return valobj->GetSP();
142061da546Spatrick   else
143061da546Spatrick     return ValueObjectSP();
144061da546Spatrick }
145061da546Spatrick 
146061da546Spatrick size_t
GetIndexOfChildWithName(ConstString name)147061da546Spatrick ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
148061da546Spatrick   if (m_reg_ctx_sp && m_reg_set) {
149061da546Spatrick     const RegisterInfo *reg_info =
150dda28197Spatrick         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
151061da546Spatrick     if (reg_info != nullptr)
152061da546Spatrick       return reg_info->kinds[eRegisterKindLLDB];
153061da546Spatrick   }
154061da546Spatrick   return UINT32_MAX;
155061da546Spatrick }
156061da546Spatrick 
157061da546Spatrick #pragma mark -
158061da546Spatrick #pragma mark ValueObjectRegister
159061da546Spatrick 
ConstructObject(const RegisterInfo * reg_info)160*f6aab3d8Srobert void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
161061da546Spatrick   if (reg_info) {
162061da546Spatrick     m_reg_info = *reg_info;
163061da546Spatrick     if (reg_info->name)
164061da546Spatrick       m_name.SetCString(reg_info->name);
165061da546Spatrick     else if (reg_info->alt_name)
166061da546Spatrick       m_name.SetCString(reg_info->alt_name);
167061da546Spatrick   }
168061da546Spatrick }
169061da546Spatrick 
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)170061da546Spatrick ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
171061da546Spatrick                                          lldb::RegisterContextSP &reg_ctx_sp,
172*f6aab3d8Srobert                                          const RegisterInfo *reg_info)
173061da546Spatrick     : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
174061da546Spatrick       m_reg_value(), m_type_name(), m_compiler_type() {
175061da546Spatrick   assert(reg_ctx_sp.get());
176*f6aab3d8Srobert   ConstructObject(reg_info);
177061da546Spatrick }
178061da546Spatrick 
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)179061da546Spatrick ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
180061da546Spatrick                                           lldb::RegisterContextSP &reg_ctx_sp,
181*f6aab3d8Srobert                                           const RegisterInfo *reg_info) {
182dda28197Spatrick   auto manager_sp = ValueObjectManager::Create();
183*f6aab3d8Srobert   return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
184dda28197Spatrick       ->GetSP();
185061da546Spatrick }
186061da546Spatrick 
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)187061da546Spatrick ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
188dda28197Spatrick                                          ValueObjectManager &manager,
189061da546Spatrick                                          lldb::RegisterContextSP &reg_ctx,
190*f6aab3d8Srobert                                          const RegisterInfo *reg_info)
191dda28197Spatrick     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
192061da546Spatrick       m_reg_value(), m_type_name(), m_compiler_type() {
193061da546Spatrick   assert(reg_ctx);
194*f6aab3d8Srobert   ConstructObject(reg_info);
195061da546Spatrick }
196061da546Spatrick 
197be691f3bSpatrick ValueObjectRegister::~ValueObjectRegister() = default;
198061da546Spatrick 
GetCompilerTypeImpl()199061da546Spatrick CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
200061da546Spatrick   if (!m_compiler_type.IsValid()) {
201061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
202061da546Spatrick     if (auto *target = exe_ctx.GetTargetPtr()) {
203061da546Spatrick       if (auto *exe_module = target->GetExecutableModulePointer()) {
204061da546Spatrick         auto type_system_or_err =
205061da546Spatrick             exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
206061da546Spatrick         if (auto err = type_system_or_err.takeError()) {
207*f6aab3d8Srobert           LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
208*f6aab3d8Srobert                          "Unable to get CompilerType from TypeSystem");
209061da546Spatrick         } else {
210*f6aab3d8Srobert           if (auto ts = *type_system_or_err)
211*f6aab3d8Srobert             m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
212061da546Spatrick                 m_reg_info.encoding, m_reg_info.byte_size * 8);
213061da546Spatrick         }
214061da546Spatrick       }
215061da546Spatrick     }
216061da546Spatrick   }
217061da546Spatrick   return m_compiler_type;
218061da546Spatrick }
219061da546Spatrick 
GetTypeName()220061da546Spatrick ConstString ValueObjectRegister::GetTypeName() {
221061da546Spatrick   if (m_type_name.IsEmpty())
222dda28197Spatrick     m_type_name = GetCompilerType().GetTypeName();
223061da546Spatrick   return m_type_name;
224061da546Spatrick }
225061da546Spatrick 
CalculateNumChildren(uint32_t max)226061da546Spatrick size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
227061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
228061da546Spatrick   auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
229061da546Spatrick   return children_count <= max ? children_count : max;
230061da546Spatrick }
231061da546Spatrick 
GetByteSize()232*f6aab3d8Srobert std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
233be691f3bSpatrick   return m_reg_info.byte_size;
234be691f3bSpatrick }
235061da546Spatrick 
UpdateValue()236061da546Spatrick bool ValueObjectRegister::UpdateValue() {
237061da546Spatrick   m_error.Clear();
238061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
239061da546Spatrick   StackFrame *frame = exe_ctx.GetFramePtr();
240061da546Spatrick   if (frame == nullptr) {
241061da546Spatrick     m_reg_ctx_sp.reset();
242061da546Spatrick     m_reg_value.Clear();
243061da546Spatrick   }
244061da546Spatrick 
245061da546Spatrick   if (m_reg_ctx_sp) {
246061da546Spatrick     RegisterValue m_old_reg_value(m_reg_value);
247061da546Spatrick     if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
248061da546Spatrick       if (m_reg_value.GetData(m_data)) {
249061da546Spatrick         Process *process = exe_ctx.GetProcessPtr();
250061da546Spatrick         if (process)
251061da546Spatrick           m_data.SetAddressByteSize(process->GetAddressByteSize());
252be691f3bSpatrick         m_value.SetContext(Value::ContextType::RegisterInfo,
253061da546Spatrick                            (void *)&m_reg_info);
254be691f3bSpatrick         m_value.SetValueType(Value::ValueType::HostAddress);
255061da546Spatrick         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
256061da546Spatrick         SetValueIsValid(true);
257061da546Spatrick         SetValueDidChange(!(m_old_reg_value == m_reg_value));
258061da546Spatrick         return true;
259061da546Spatrick       }
260061da546Spatrick     }
261061da546Spatrick   }
262061da546Spatrick 
263061da546Spatrick   SetValueIsValid(false);
264061da546Spatrick   m_error.SetErrorToGenericError();
265061da546Spatrick   return false;
266061da546Spatrick }
267061da546Spatrick 
SetValueFromCString(const char * value_str,Status & error)268061da546Spatrick bool ValueObjectRegister::SetValueFromCString(const char *value_str,
269061da546Spatrick                                               Status &error) {
270061da546Spatrick   // The new value will be in the m_data.  Copy that into our register value.
271061da546Spatrick   error =
272061da546Spatrick       m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
273*f6aab3d8Srobert   if (!error.Success())
274061da546Spatrick     return false;
275*f6aab3d8Srobert 
276*f6aab3d8Srobert   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
277*f6aab3d8Srobert     error.SetErrorString("unable to write back to register");
278061da546Spatrick     return false;
279061da546Spatrick   }
280061da546Spatrick 
281061da546Spatrick   SetNeedsUpdate();
282061da546Spatrick   return true;
283*f6aab3d8Srobert }
284*f6aab3d8Srobert 
SetData(DataExtractor & data,Status & error)285*f6aab3d8Srobert bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
286*f6aab3d8Srobert   error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
287*f6aab3d8Srobert   if (!error.Success())
288061da546Spatrick     return false;
289*f6aab3d8Srobert 
290*f6aab3d8Srobert   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
291*f6aab3d8Srobert     error.SetErrorString("unable to write back to register");
292061da546Spatrick     return false;
293061da546Spatrick   }
294061da546Spatrick 
295*f6aab3d8Srobert   SetNeedsUpdate();
296*f6aab3d8Srobert   return true;
297*f6aab3d8Srobert }
298*f6aab3d8Srobert 
ResolveValue(Scalar & scalar)299061da546Spatrick bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
300061da546Spatrick   if (UpdateValueIfNeeded(
301061da546Spatrick           false)) // make sure that you are up to date before returning anything
302061da546Spatrick     return m_reg_value.GetScalarValue(scalar);
303061da546Spatrick   return false;
304061da546Spatrick }
305061da546Spatrick 
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)306061da546Spatrick void ValueObjectRegister::GetExpressionPath(Stream &s,
307061da546Spatrick                                             GetExpressionPathFormat epformat) {
308061da546Spatrick   s.Printf("$%s", m_reg_info.name);
309061da546Spatrick }
310