xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 #include <optional>
32 
33 namespace lldb_private {
34 class ExecutionContextScope;
35 }
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 #pragma mark ValueObjectRegisterSet
41 
42 ValueObjectSP
43 ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
44                                lldb::RegisterContextSP &reg_ctx_sp,
45                                uint32_t set_idx) {
46   auto manager_sp = ValueObjectManager::Create();
47   return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
48                                      set_idx))
49       ->GetSP();
50 }
51 
52 ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53                                                ValueObjectManager &manager,
54                                                lldb::RegisterContextSP &reg_ctx,
55                                                uint32_t reg_set_idx)
56     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
57       m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
58   assert(reg_ctx);
59   m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
60   if (m_reg_set) {
61     m_name.SetCString(m_reg_set->name);
62   }
63 }
64 
65 ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66 
67 CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68   return CompilerType();
69 }
70 
71 ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72 
73 ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74   return ConstString();
75 }
76 
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);
80   if (reg_set) {
81     auto reg_count = reg_set->num_registers;
82     return reg_count <= max ? reg_count : max;
83   }
84   return 0;
85 }
86 
87 std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
88 
89 bool ValueObjectRegisterSet::UpdateValue() {
90   m_error.Clear();
91   SetValueDidChange(false);
92   ExecutionContext exe_ctx(GetExecutionContextRef());
93   StackFrame *frame = exe_ctx.GetFramePtr();
94   if (frame == nullptr)
95     m_reg_ctx_sp.reset();
96   else {
97     m_reg_ctx_sp = frame->GetRegisterContext();
98     if (m_reg_ctx_sp) {
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);
105       }
106     }
107   }
108   if (m_reg_ctx_sp) {
109     SetValueIsValid(true);
110   } else {
111     SetValueIsValid(false);
112     m_error.SetErrorToGenericError();
113     m_children.Clear();
114   }
115   return m_error.Success();
116 }
117 
118 ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {
119   if (m_reg_ctx_sp && m_reg_set) {
120     return new ValueObjectRegister(
121         *this, m_reg_ctx_sp,
122         m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
123   }
124   return nullptr;
125 }
126 
127 lldb::ValueObjectSP
128 ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
129                                                bool can_create) {
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);
135   }
136   if (valobj)
137     return valobj->GetSP();
138   else
139     return ValueObjectSP();
140 }
141 
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];
147   }
148   return UINT32_MAX;
149 }
150 
151 #pragma mark -
152 #pragma mark ValueObjectRegister
153 
154 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
155   if (reg_info) {
156     m_reg_info = *reg_info;
157     if (reg_info->name)
158       m_name.SetCString(reg_info->name);
159     else if (reg_info->alt_name)
160       m_name.SetCString(reg_info->alt_name);
161   }
162 }
163 
164 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
165                                          lldb::RegisterContextSP &reg_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);
171 }
172 
173 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
174                                           lldb::RegisterContextSP &reg_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))
178       ->GetSP();
179 }
180 
181 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
182                                          ValueObjectManager &manager,
183                                          lldb::RegisterContextSP &reg_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() {
187   assert(reg_ctx);
188   ConstructObject(reg_info);
189 }
190 
191 ValueObjectRegister::~ValueObjectRegister() = default;
192 
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}");
203         } else {
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);
207         }
208       }
209     }
210   }
211   return m_compiler_type;
212 }
213 
214 ConstString ValueObjectRegister::GetTypeName() {
215   if (m_type_name.IsEmpty())
216     m_type_name = GetCompilerType().GetTypeName();
217   return m_type_name;
218 }
219 
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);
224   if (!children_count)
225     return children_count;
226   return *children_count <= max ? *children_count : max;
227 }
228 
229 std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
230   return m_reg_info.byte_size;
231 }
232 
233 bool ValueObjectRegister::UpdateValue() {
234   m_error.Clear();
235   ExecutionContext exe_ctx(GetExecutionContextRef());
236   StackFrame *frame = exe_ctx.GetFramePtr();
237   if (frame == nullptr) {
238     m_reg_ctx_sp.reset();
239     m_reg_value.Clear();
240   }
241 
242   if (m_reg_ctx_sp) {
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();
247         if (process)
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));
255         return true;
256       }
257     }
258   }
259 
260   SetValueIsValid(false);
261   m_error.SetErrorToGenericError();
262   return false;
263 }
264 
265 bool ValueObjectRegister::SetValueFromCString(const char *value_str,
266                                               Status &error) {
267   // The new value will be in the m_data.  Copy that into our register value.
268   error =
269       m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
270   if (!error.Success())
271     return false;
272 
273   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
274     error.SetErrorString("unable to write back to register");
275     return false;
276   }
277 
278   SetNeedsUpdate();
279   return true;
280 }
281 
282 bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
283   error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
284   if (!error.Success())
285     return false;
286 
287   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
288     error.SetErrorString("unable to write back to register");
289     return false;
290   }
291 
292   SetNeedsUpdate();
293   return true;
294 }
295 
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);
300   return false;
301 }
302 
303 void ValueObjectRegister::GetExpressionPath(Stream &s,
304                                             GetExpressionPathFormat epformat) {
305   s.Printf("$%s", m_reg_info.name);
306 }
307