blob: 05022d3ed10a48e25820ab62ebbfbbd199c1b690 [file] [log] [blame]
//===-- ValueObjectRegister.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Scalar.h" // for Scalar
#include "lldb/Core/Value.h" // for Value, Value::ContextType:...
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/TypeSystem.h" // for TypeSystem
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h" // for StackFrame
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h" // for DataExtractor
#include "lldb/Utility/Status.h" // for Status
#include "lldb/Utility/Stream.h" // for Stream
#include "llvm/ADT/StringRef.h" // for StringRef
#include <assert.h> // for assert
#include <memory> // for shared_ptr
namespace lldb_private {
class ExecutionContextScope;
}
using namespace lldb;
using namespace lldb_private;
#pragma mark ValueObjectRegisterContext
ValueObjectRegisterContext::ValueObjectRegisterContext(
ValueObject &parent, RegisterContextSP &reg_ctx)
: ValueObject(parent), m_reg_ctx_sp(reg_ctx) {
assert(reg_ctx);
m_name.SetCString("Registers");
SetValueIsValid(true);
}
ValueObjectRegisterContext::~ValueObjectRegisterContext() {}
CompilerType ValueObjectRegisterContext::GetCompilerTypeImpl() {
return CompilerType();
}
ConstString ValueObjectRegisterContext::GetTypeName() { return ConstString(); }
ConstString ValueObjectRegisterContext::GetDisplayTypeName() {
return ConstString();
}
ConstString ValueObjectRegisterContext::GetQualifiedTypeName() {
return ConstString();
}
size_t ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) {
auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount();
return reg_set_count <= max ? reg_set_count : max;
}
uint64_t ValueObjectRegisterContext::GetByteSize() { return 0; }
bool ValueObjectRegisterContext::UpdateValue() {
m_error.Clear();
ExecutionContext exe_ctx(GetExecutionContextRef());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame)
m_reg_ctx_sp = frame->GetRegisterContext();
else
m_reg_ctx_sp.reset();
if (m_reg_ctx_sp.get() == NULL) {
SetValueIsValid(false);
m_error.SetErrorToGenericError();
} else
SetValueIsValid(true);
return m_error.Success();
}
ValueObject *ValueObjectRegisterContext::CreateChildAtIndex(
size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
ValueObject *new_valobj = NULL;
const size_t num_children = GetNumChildren();
if (idx < num_children) {
ExecutionContext exe_ctx(GetExecutionContextRef());
new_valobj = new ValueObjectRegisterSet(
exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx);
}
return new_valobj;
}
#pragma mark -
#pragma mark ValueObjectRegisterSet
ValueObjectSP
ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx_sp,
uint32_t set_idx) {
return (new ValueObjectRegisterSet(exe_scope, reg_ctx_sp, set_idx))->GetSP();
}
ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx,
uint32_t reg_set_idx)
: ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_set(NULL),
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() {}
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;
}
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 == NULL)
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 == NULL)
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 = NULL;
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_set->registers[idx]);
}
return valobj;
}
lldb::ValueObjectSP
ValueObjectRegisterSet::GetChildMemberWithName(const ConstString &name,
bool can_create) {
ValueObject *valobj = NULL;
if (m_reg_ctx_sp && m_reg_set) {
const RegisterInfo *reg_info =
m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString());
if (reg_info != NULL)
valobj = new ValueObjectRegister(*this, m_reg_ctx_sp,
reg_info->kinds[eRegisterKindLLDB]);
}
if (valobj)
return valobj->GetSP();
else
return ValueObjectSP();
}
size_t
ValueObjectRegisterSet::GetIndexOfChildWithName(const ConstString &name) {
if (m_reg_ctx_sp && m_reg_set) {
const RegisterInfo *reg_info =
m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString());
if (reg_info != NULL)
return reg_info->kinds[eRegisterKindLLDB];
}
return UINT32_MAX;
}
#pragma mark -
#pragma mark ValueObjectRegister
void ValueObjectRegister::ConstructObject(uint32_t reg_num) {
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
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);
}
}
ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
lldb::RegisterContextSP &reg_ctx_sp,
uint32_t reg_num)
: ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
m_reg_value(), m_type_name(), m_compiler_type() {
assert(reg_ctx_sp.get());
ConstructObject(reg_num);
}
ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx_sp,
uint32_t reg_num) {
return (new ValueObjectRegister(exe_scope, reg_ctx_sp, reg_num))->GetSP();
}
ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
lldb::RegisterContextSP &reg_ctx,
uint32_t reg_num)
: ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_info(),
m_reg_value(), m_type_name(), m_compiler_type() {
assert(reg_ctx);
ConstructObject(reg_num);
}
ValueObjectRegister::~ValueObjectRegister() {}
CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
if (!m_compiler_type.IsValid()) {
ExecutionContext exe_ctx(GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
if (target) {
Module *exe_module = target->GetExecutableModulePointer();
if (exe_module) {
TypeSystem *type_system =
exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
if (type_system)
m_compiler_type = type_system->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().GetConstTypeName();
return m_type_name;
}
size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
auto children_count = GetCompilerType().GetNumChildren(true);
return children_count <= max ? children_count : max;
}
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 == NULL) {
m_reg_ctx_sp.reset();
m_reg_value.Clear();
}
if (m_reg_ctx_sp) {
RegisterValue m_old_reg_value(m_reg_value);
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::eContextTypeRegisterInfo,
(void *)&m_reg_info);
m_value.SetValueType(Value::eValueTypeHostAddress);
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
SetValueIsValid(true);
SetValueDidChange(!(m_old_reg_value == m_reg_value));
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()) {
if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
SetNeedsUpdate();
return true;
} else
return false;
} else
return false;
}
bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
if (error.Success()) {
if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
SetNeedsUpdate();
return true;
} else
return false;
} else
return false;
}
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,
bool qualify_cxx_base_classes,
GetExpressionPathFormat epformat) {
s.Printf("$%s", m_reg_info.name);
}