Files
llvm/lldb/source/Core/ValueObjectRegister.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

307 lines
9.8 KiB
C++
Raw Normal View History

//===-- ValueObjectRegister.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <memory>
#include <optional>
namespace lldb_private {
class ExecutionContextScope;
}
using namespace lldb;
using namespace lldb_private;
#pragma mark ValueObjectRegisterSet
ValueObjectSP
ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx_sp,
uint32_t set_idx) {
auto manager_sp = ValueObjectManager::Create();
return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
set_idx))
->GetSP();
}
ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
ValueObjectManager &manager,
lldb::RegisterContextSP &reg_ctx,
uint32_t reg_set_idx)
: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
assert(reg_ctx);
m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
if (m_reg_set) {
m_name.SetCString(m_reg_set->name);
}
}
ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
Final bit of type system cleanup that abstracts declaration contexts into lldb_private::CompilerDeclContext and renames ClangType to CompilerType in many accessors and functions. Create a new "lldb_private::CompilerDeclContext" class that will replace all direct uses of "clang::DeclContext" when used in compiler agnostic code, yet still allow for conversion to clang::DeclContext subclasses by clang specific code. This completes the abstraction of type parsing by removing all "clang::" references from the SymbolFileDWARF. The new "lldb_private::CompilerDeclContext" class abstracts decl contexts found in compiler type systems so they can be used in internal API calls. The TypeSystem is required to support CompilerDeclContexts with new pure virtual functions that start with "DeclContext" in the member function names. Converted all code that used lldb_private::ClangNamespaceDecl over to use the new CompilerDeclContext class and removed the ClangNamespaceDecl.cpp and ClangNamespaceDecl.h files. Removed direct use of clang APIs from SBType and now use the abstract type systems to correctly explore types. Bulk renames for things that used to return a ClangASTType which is now CompilerType: "Type::GetClangFullType()" to "Type::GetFullCompilerType()" "Type::GetClangLayoutType()" to "Type::GetLayoutCompilerType()" "Type::GetClangForwardType()" to "Type::GetForwardCompilerType()" "Value::GetClangType()" to "Value::GetCompilerType()" "Value::SetClangType (const CompilerType &)" to "Value::SetCompilerType (const CompilerType &)" "ValueObject::GetClangType ()" to "ValueObject::GetCompilerType()" many more renames that are similar. llvm-svn: 245905
2015-08-24 23:46:31 +00:00
CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
return CompilerType();
}
ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
return ConstString();
}
size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
if (reg_set) {
auto reg_count = reg_set->num_registers;
return reg_count <= max ? reg_count : max;
}
return 0;
}
std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
bool ValueObjectRegisterSet::UpdateValue() {
m_error.Clear();
SetValueDidChange(false);
ExecutionContext exe_ctx(GetExecutionContextRef());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == nullptr)
m_reg_ctx_sp.reset();
else {
m_reg_ctx_sp = frame->GetRegisterContext();
if (m_reg_ctx_sp) {
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
if (reg_set == nullptr)
m_reg_ctx_sp.reset();
else if (m_reg_set != reg_set) {
SetValueDidChange(true);
m_name.SetCString(reg_set->name);
}
}
}
if (m_reg_ctx_sp) {
SetValueIsValid(true);
} else {
SetValueIsValid(false);
m_error.SetErrorToGenericError();
m_children.Clear();
}
return m_error.Success();
}
ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
ValueObject *valobj = nullptr;
if (m_reg_ctx_sp && m_reg_set) {
const size_t num_children = GetNumChildren();
if (idx < num_children)
valobj = new ValueObjectRegister(
*this, m_reg_ctx_sp,
m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
}
return valobj;
}
lldb::ValueObjectSP
ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
bool can_create) {
ValueObject *valobj = nullptr;
if (m_reg_ctx_sp && m_reg_set) {
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
if (reg_info != nullptr)
valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
}
if (valobj)
return valobj->GetSP();
else
return ValueObjectSP();
}
size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
if (m_reg_ctx_sp && m_reg_set) {
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
if (reg_info != nullptr)
return reg_info->kinds[eRegisterKindLLDB];
}
return UINT32_MAX;
}
#pragma mark -
#pragma mark ValueObjectRegister
void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
2011-05-09 20:18:18 +00:00
if (reg_info) {
m_reg_info = *reg_info;
if (reg_info->name)
m_name.SetCString(reg_info->name);
else if (reg_info->alt_name)
m_name.SetCString(reg_info->alt_name);
}
}
Final bit of type system cleanup that abstracts declaration contexts into lldb_private::CompilerDeclContext and renames ClangType to CompilerType in many accessors and functions. Create a new "lldb_private::CompilerDeclContext" class that will replace all direct uses of "clang::DeclContext" when used in compiler agnostic code, yet still allow for conversion to clang::DeclContext subclasses by clang specific code. This completes the abstraction of type parsing by removing all "clang::" references from the SymbolFileDWARF. The new "lldb_private::CompilerDeclContext" class abstracts decl contexts found in compiler type systems so they can be used in internal API calls. The TypeSystem is required to support CompilerDeclContexts with new pure virtual functions that start with "DeclContext" in the member function names. Converted all code that used lldb_private::ClangNamespaceDecl over to use the new CompilerDeclContext class and removed the ClangNamespaceDecl.cpp and ClangNamespaceDecl.h files. Removed direct use of clang APIs from SBType and now use the abstract type systems to correctly explore types. Bulk renames for things that used to return a ClangASTType which is now CompilerType: "Type::GetClangFullType()" to "Type::GetFullCompilerType()" "Type::GetClangLayoutType()" to "Type::GetLayoutCompilerType()" "Type::GetClangForwardType()" to "Type::GetForwardCompilerType()" "Value::GetClangType()" to "Value::GetCompilerType()" "Value::SetClangType (const CompilerType &)" to "Value::SetCompilerType (const CompilerType &)" "ValueObject::GetClangType ()" to "ValueObject::GetCompilerType()" many more renames that are similar. llvm-svn: 245905
2015-08-24 23:46:31 +00:00
ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
lldb::RegisterContextSP &reg_ctx_sp,
const RegisterInfo *reg_info)
: ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
m_reg_value(), m_type_name(), m_compiler_type() {
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-17 22:23:34 +00:00
assert(reg_ctx_sp.get());
ConstructObject(reg_info);
}
ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx_sp,
const RegisterInfo *reg_info) {
auto manager_sp = ValueObjectManager::Create();
return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
->GetSP();
}
ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
ValueObjectManager &manager,
lldb::RegisterContextSP &reg_ctx,
const RegisterInfo *reg_info)
: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
m_reg_value(), m_type_name(), m_compiler_type() {
assert(reg_ctx);
ConstructObject(reg_info);
}
ValueObjectRegister::~ValueObjectRegister() = default;
CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
if (!m_compiler_type.IsValid()) {
ExecutionContext exe_ctx(GetExecutionContextRef());
if (auto *target = exe_ctx.GetTargetPtr()) {
if (auto *exe_module = target->GetExecutableModulePointer()) {
auto type_system_or_err =
TypeSystem is now a plugin interface and removed any "ClangASTContext &Class::GetClangASTContext()" functions. This cleans up type systems to be more pluggable. Prior to this we had issues: - Module, SymbolFile, and many others has "ClangASTContext &GetClangASTContext()" functions. All have been switched over to use "TypeSystem *GetTypeSystemForLanguage()" - Cleaned up any places that were using the GetClangASTContext() functions to use TypeSystem - Cleaned up Module so that it no longer has dedicated type system member variables: lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module. lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module. Now we have a type system map: typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> TypeSystemMap; TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module - Many places in code were using ClangASTContext static functions to place with CompilerType objects and add modifiers (const, volatile, restrict) and to make typedefs, L and R value references and more. These have been made into CompilerType functions that are abstract: class CompilerType { ... //---------------------------------------------------------------------- // Return a new CompilerType that is a L value reference to this type if // this type is valid and the type system supports L value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetLValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType that is a R value reference to this type if // this type is valid and the type system supports R value references, // else return an invalid type. //---------------------------------------------------------------------- CompilerType GetRValueReferenceType () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a const modifier to this type if // this type is valid and the type system supports const modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddConstModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a volatile modifier to this type if // this type is valid and the type system supports volatile modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddVolatileModifier () const; //---------------------------------------------------------------------- // Return a new CompilerType adds a restrict modifier to this type if // this type is valid and the type system supports restrict modifiers, // else return an invalid type. //---------------------------------------------------------------------- CompilerType AddRestrictModifier () const; //---------------------------------------------------------------------- // Create a typedef to this type using "name" as the name of the typedef // this type is valid and the type system supports typedefs, else return // an invalid type. //---------------------------------------------------------------------- CompilerType CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; }; Other changes include: - Removed "CompilerType TypeSystem::GetIntTypeFromBitSize(...)" and CompilerType TypeSystem::GetFloatTypeFromBitSize(...) and replaced it with "CompilerType TypeSystem::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size);" - Fixed code in Type.h to not request the full type for a type for no good reason, just request the forward type and let the type expand as needed llvm-svn: 247953
2015-09-17 22:23:34 +00:00
exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
if (auto err = type_system_or_err.takeError()) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
"Unable to get CompilerType from TypeSystem");
} else {
if (auto ts = *type_system_or_err)
m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
m_reg_info.encoding, m_reg_info.byte_size * 8);
}
}
}
}
return m_compiler_type;
}
ConstString ValueObjectRegister::GetTypeName() {
if (m_type_name.IsEmpty())
m_type_name = GetCompilerType().GetTypeName();
return m_type_name;
}
size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
ExecutionContext exe_ctx(GetExecutionContextRef());
auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
return children_count <= max ? children_count : max;
}
std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
return m_reg_info.byte_size;
}
bool ValueObjectRegister::UpdateValue() {
m_error.Clear();
ExecutionContext exe_ctx(GetExecutionContextRef());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == nullptr) {
m_reg_ctx_sp.reset();
2011-05-09 20:18:18 +00:00
m_reg_value.Clear();
}
2011-05-09 20:18:18 +00:00
if (m_reg_ctx_sp) {
RegisterValue m_old_reg_value(m_reg_value);
2011-05-09 20:18:18 +00:00
if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
if (m_reg_value.GetData(m_data)) {
Process *process = exe_ctx.GetProcessPtr();
if (process)
m_data.SetAddressByteSize(process->GetAddressByteSize());
m_value.SetContext(Value::ContextType::RegisterInfo,
2011-05-09 20:18:18 +00:00
(void *)&m_reg_info);
m_value.SetValueType(Value::ValueType::HostAddress);
2011-05-09 20:18:18 +00:00
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
SetValueIsValid(true);
SetValueDidChange(!(m_old_reg_value == m_reg_value));
2011-05-09 20:18:18 +00:00
return true;
}
}
}
SetValueIsValid(false);
m_error.SetErrorToGenericError();
return false;
}
bool ValueObjectRegister::SetValueFromCString(const char *value_str,
Status &error) {
// The new value will be in the m_data. Copy that into our register value.
error =
m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
if (!error.Success())
return false;
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
error.SetErrorString("unable to write back to register");
return false;
}
SetNeedsUpdate();
return true;
}
bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
if (!error.Success())
return false;
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
error.SetErrorString("unable to write back to register");
return false;
}
SetNeedsUpdate();
return true;
}
bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
if (UpdateValueIfNeeded(
false)) // make sure that you are up to date before returning anything
return m_reg_value.GetScalarValue(scalar);
return false;
}
void ValueObjectRegister::GetExpressionPath(Stream &s,
GetExpressionPathFormat epformat) {
s.Printf("$%s", m_reg_info.name);
}