xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- ValueObjectRegister.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectRegister.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Module.h"
120b57cec5SDimitry Andric #include "lldb/Core/Value.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
140b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h"
150b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
160b57cec5SDimitry Andric #include "lldb/Target/Process.h"
170b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
180b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
190b57cec5SDimitry Andric #include "lldb/Target/Target.h"
200b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
2181ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
229dba64beSDimitry Andric #include "lldb/Utility/Log.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
240b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
250b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
280b57cec5SDimitry Andric 
29fe6060f1SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <memory>
31bdd1243dSDimitry Andric #include <optional>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace lldb_private {
340b57cec5SDimitry Andric class ExecutionContextScope;
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace lldb;
380b57cec5SDimitry Andric using namespace lldb_private;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #pragma mark ValueObjectRegisterSet
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric ValueObjectSP
430b57cec5SDimitry Andric ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
440b57cec5SDimitry Andric                                lldb::RegisterContextSP &reg_ctx_sp,
450b57cec5SDimitry Andric                                uint32_t set_idx) {
465ffd83dbSDimitry Andric   auto manager_sp = ValueObjectManager::Create();
475ffd83dbSDimitry Andric   return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
485ffd83dbSDimitry Andric                                      set_idx))
495ffd83dbSDimitry Andric       ->GetSP();
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
535ffd83dbSDimitry Andric                                                ValueObjectManager &manager,
540b57cec5SDimitry Andric                                                lldb::RegisterContextSP &reg_ctx,
550b57cec5SDimitry Andric                                                uint32_t reg_set_idx)
565ffd83dbSDimitry Andric     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
575ffd83dbSDimitry Andric       m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
580b57cec5SDimitry Andric   assert(reg_ctx);
590b57cec5SDimitry Andric   m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
600b57cec5SDimitry Andric   if (m_reg_set) {
610b57cec5SDimitry Andric     m_name.SetCString(m_reg_set->name);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
65fe6060f1SDimitry Andric ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
680b57cec5SDimitry Andric   return CompilerType();
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
740b57cec5SDimitry Andric   return ConstString();
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
77*0fca6ea1SDimitry Andric llvm::Expected<uint32_t>
78*0fca6ea1SDimitry Andric ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
790b57cec5SDimitry Andric   const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
800b57cec5SDimitry Andric   if (reg_set) {
810b57cec5SDimitry Andric     auto reg_count = reg_set->num_registers;
820b57cec5SDimitry Andric     return reg_count <= max ? reg_count : max;
830b57cec5SDimitry Andric   }
840b57cec5SDimitry Andric   return 0;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
87bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric bool ValueObjectRegisterSet::UpdateValue() {
900b57cec5SDimitry Andric   m_error.Clear();
910b57cec5SDimitry Andric   SetValueDidChange(false);
920b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
930b57cec5SDimitry Andric   StackFrame *frame = exe_ctx.GetFramePtr();
940b57cec5SDimitry Andric   if (frame == nullptr)
950b57cec5SDimitry Andric     m_reg_ctx_sp.reset();
960b57cec5SDimitry Andric   else {
970b57cec5SDimitry Andric     m_reg_ctx_sp = frame->GetRegisterContext();
980b57cec5SDimitry Andric     if (m_reg_ctx_sp) {
990b57cec5SDimitry Andric       const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
1000b57cec5SDimitry Andric       if (reg_set == nullptr)
1010b57cec5SDimitry Andric         m_reg_ctx_sp.reset();
1020b57cec5SDimitry Andric       else if (m_reg_set != reg_set) {
1030b57cec5SDimitry Andric         SetValueDidChange(true);
1040b57cec5SDimitry Andric         m_name.SetCString(reg_set->name);
1050b57cec5SDimitry Andric       }
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric   if (m_reg_ctx_sp) {
1090b57cec5SDimitry Andric     SetValueIsValid(true);
1100b57cec5SDimitry Andric   } else {
1110b57cec5SDimitry Andric     SetValueIsValid(false);
1120b57cec5SDimitry Andric     m_error.SetErrorToGenericError();
1130b57cec5SDimitry Andric     m_children.Clear();
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric   return m_error.Success();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
118*0fca6ea1SDimitry Andric ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {
1190b57cec5SDimitry Andric   if (m_reg_ctx_sp && m_reg_set) {
120*0fca6ea1SDimitry Andric     return new ValueObjectRegister(
121349cc55cSDimitry Andric         *this, m_reg_ctx_sp,
122349cc55cSDimitry Andric         m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
1230b57cec5SDimitry Andric   }
124*0fca6ea1SDimitry Andric   return nullptr;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric lldb::ValueObjectSP
12806c3fb27SDimitry Andric ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
1290b57cec5SDimitry Andric                                                bool can_create) {
1300b57cec5SDimitry Andric   ValueObject *valobj = nullptr;
1310b57cec5SDimitry Andric   if (m_reg_ctx_sp && m_reg_set) {
13206c3fb27SDimitry Andric     const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
1330b57cec5SDimitry Andric     if (reg_info != nullptr)
134349cc55cSDimitry Andric       valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric   if (valobj)
1370b57cec5SDimitry Andric     return valobj->GetSP();
1380b57cec5SDimitry Andric   else
1390b57cec5SDimitry Andric     return ValueObjectSP();
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
14206c3fb27SDimitry Andric size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
1430b57cec5SDimitry Andric   if (m_reg_ctx_sp && m_reg_set) {
14406c3fb27SDimitry Andric     const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
1450b57cec5SDimitry Andric     if (reg_info != nullptr)
1460b57cec5SDimitry Andric       return reg_info->kinds[eRegisterKindLLDB];
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric   return UINT32_MAX;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric #pragma mark -
1520b57cec5SDimitry Andric #pragma mark ValueObjectRegister
1530b57cec5SDimitry Andric 
154349cc55cSDimitry Andric void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
1550b57cec5SDimitry Andric   if (reg_info) {
1560b57cec5SDimitry Andric     m_reg_info = *reg_info;
1570b57cec5SDimitry Andric     if (reg_info->name)
1580b57cec5SDimitry Andric       m_name.SetCString(reg_info->name);
1590b57cec5SDimitry Andric     else if (reg_info->alt_name)
1600b57cec5SDimitry Andric       m_name.SetCString(reg_info->alt_name);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
1650b57cec5SDimitry Andric                                          lldb::RegisterContextSP &reg_ctx_sp,
166349cc55cSDimitry Andric                                          const RegisterInfo *reg_info)
1670b57cec5SDimitry Andric     : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
1680b57cec5SDimitry Andric       m_reg_value(), m_type_name(), m_compiler_type() {
1690b57cec5SDimitry Andric   assert(reg_ctx_sp.get());
170349cc55cSDimitry Andric   ConstructObject(reg_info);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
1740b57cec5SDimitry Andric                                           lldb::RegisterContextSP &reg_ctx_sp,
175349cc55cSDimitry Andric                                           const RegisterInfo *reg_info) {
1765ffd83dbSDimitry Andric   auto manager_sp = ValueObjectManager::Create();
177349cc55cSDimitry Andric   return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
1785ffd83dbSDimitry Andric       ->GetSP();
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
1825ffd83dbSDimitry Andric                                          ValueObjectManager &manager,
1830b57cec5SDimitry Andric                                          lldb::RegisterContextSP &reg_ctx,
184349cc55cSDimitry Andric                                          const RegisterInfo *reg_info)
1855ffd83dbSDimitry Andric     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
1860b57cec5SDimitry Andric       m_reg_value(), m_type_name(), m_compiler_type() {
1870b57cec5SDimitry Andric   assert(reg_ctx);
188349cc55cSDimitry Andric   ConstructObject(reg_info);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
191fe6060f1SDimitry Andric ValueObjectRegister::~ValueObjectRegister() = default;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
1940b57cec5SDimitry Andric   if (!m_compiler_type.IsValid()) {
1950b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
1969dba64beSDimitry Andric     if (auto *target = exe_ctx.GetTargetPtr()) {
1979dba64beSDimitry Andric       if (auto *exe_module = target->GetExecutableModulePointer()) {
1989dba64beSDimitry Andric         auto type_system_or_err =
1990b57cec5SDimitry Andric             exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
2009dba64beSDimitry Andric         if (auto err = type_system_or_err.takeError()) {
20181ad6265SDimitry Andric           LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
20206c3fb27SDimitry Andric                          "Unable to get CompilerType from TypeSystem: {0}");
2039dba64beSDimitry Andric         } else {
204bdd1243dSDimitry Andric           if (auto ts = *type_system_or_err)
205bdd1243dSDimitry Andric             m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
2060b57cec5SDimitry Andric                 m_reg_info.encoding, m_reg_info.byte_size * 8);
2070b57cec5SDimitry Andric         }
2080b57cec5SDimitry Andric       }
2090b57cec5SDimitry Andric     }
2109dba64beSDimitry Andric   }
2110b57cec5SDimitry Andric   return m_compiler_type;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric ConstString ValueObjectRegister::GetTypeName() {
2150b57cec5SDimitry Andric   if (m_type_name.IsEmpty())
2165ffd83dbSDimitry Andric     m_type_name = GetCompilerType().GetTypeName();
2170b57cec5SDimitry Andric   return m_type_name;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
220*0fca6ea1SDimitry Andric llvm::Expected<uint32_t>
221*0fca6ea1SDimitry Andric ValueObjectRegister::CalculateNumChildren(uint32_t max) {
2220b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
2230b57cec5SDimitry Andric   auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
224*0fca6ea1SDimitry Andric   if (!children_count)
225*0fca6ea1SDimitry Andric     return children_count;
226*0fca6ea1SDimitry Andric   return *children_count <= max ? *children_count : max;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
229bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
230e8d8bef9SDimitry Andric   return m_reg_info.byte_size;
231e8d8bef9SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric bool ValueObjectRegister::UpdateValue() {
2340b57cec5SDimitry Andric   m_error.Clear();
2350b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
2360b57cec5SDimitry Andric   StackFrame *frame = exe_ctx.GetFramePtr();
2370b57cec5SDimitry Andric   if (frame == nullptr) {
2380b57cec5SDimitry Andric     m_reg_ctx_sp.reset();
2390b57cec5SDimitry Andric     m_reg_value.Clear();
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   if (m_reg_ctx_sp) {
2430b57cec5SDimitry Andric     RegisterValue m_old_reg_value(m_reg_value);
2440b57cec5SDimitry Andric     if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
2450b57cec5SDimitry Andric       if (m_reg_value.GetData(m_data)) {
2460b57cec5SDimitry Andric         Process *process = exe_ctx.GetProcessPtr();
2470b57cec5SDimitry Andric         if (process)
2480b57cec5SDimitry Andric           m_data.SetAddressByteSize(process->GetAddressByteSize());
249fe6060f1SDimitry Andric         m_value.SetContext(Value::ContextType::RegisterInfo,
2500b57cec5SDimitry Andric                            (void *)&m_reg_info);
251fe6060f1SDimitry Andric         m_value.SetValueType(Value::ValueType::HostAddress);
2520b57cec5SDimitry Andric         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
2530b57cec5SDimitry Andric         SetValueIsValid(true);
2540b57cec5SDimitry Andric         SetValueDidChange(!(m_old_reg_value == m_reg_value));
2550b57cec5SDimitry Andric         return true;
2560b57cec5SDimitry Andric       }
2570b57cec5SDimitry Andric     }
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   SetValueIsValid(false);
2610b57cec5SDimitry Andric   m_error.SetErrorToGenericError();
2620b57cec5SDimitry Andric   return false;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric bool ValueObjectRegister::SetValueFromCString(const char *value_str,
2660b57cec5SDimitry Andric                                               Status &error) {
2670b57cec5SDimitry Andric   // The new value will be in the m_data.  Copy that into our register value.
2680b57cec5SDimitry Andric   error =
2690b57cec5SDimitry Andric       m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
27081ad6265SDimitry Andric   if (!error.Success())
27181ad6265SDimitry Andric     return false;
27281ad6265SDimitry Andric 
27381ad6265SDimitry Andric   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
27481ad6265SDimitry Andric     error.SetErrorString("unable to write back to register");
27581ad6265SDimitry Andric     return false;
27681ad6265SDimitry Andric   }
27781ad6265SDimitry Andric 
2780b57cec5SDimitry Andric   SetNeedsUpdate();
2790b57cec5SDimitry Andric   return true;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
283bdd1243dSDimitry Andric   error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
28481ad6265SDimitry Andric   if (!error.Success())
28581ad6265SDimitry Andric     return false;
28681ad6265SDimitry Andric 
28781ad6265SDimitry Andric   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
28881ad6265SDimitry Andric     error.SetErrorString("unable to write back to register");
28981ad6265SDimitry Andric     return false;
29081ad6265SDimitry Andric   }
29181ad6265SDimitry Andric 
2920b57cec5SDimitry Andric   SetNeedsUpdate();
2930b57cec5SDimitry Andric   return true;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
2970b57cec5SDimitry Andric   if (UpdateValueIfNeeded(
2980b57cec5SDimitry Andric           false)) // make sure that you are up to date before returning anything
2990b57cec5SDimitry Andric     return m_reg_value.GetScalarValue(scalar);
3000b57cec5SDimitry Andric   return false;
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric void ValueObjectRegister::GetExpressionPath(Stream &s,
3040b57cec5SDimitry Andric                                             GetExpressionPathFormat epformat) {
3050b57cec5SDimitry Andric   s.Printf("$%s", m_reg_info.name);
3060b57cec5SDimitry Andric }
307