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

360 lines
11 KiB
C++
Raw Normal View History

//===-- 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/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/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include <assert.h>
#include <memory>
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();
Introduce the concept of a "display name" for types Rationale: Pretty simply, the idea is that sometimes type names are way too long and contain way too many details for the average developer to care about. For instance, a plain ol' vector of int might be shown as std::__1::vector<int, std::__1::allocator<.... rather than the much simpler std::vector<int> form, which is what most developers would actually type in their code Proposed solution: Introduce a notion of "display name" and a corresponding API GetDisplayTypeName() to return such a crafted for visual representation type name Obviously, the display name and the fully qualified (or "true") name are not necessarily the same - that's the whole point LLDB could choose to pick the "display name" as its one true notion of a type name, and if somebody really needs the fully qualified version of it, let them deal with the problem Or, LLDB could rename what it currently calls the "type name" to be the "display name", and add new APIs for the fully qualified name, making the display name the default choice The choice that I am making here is that the type name will keep meaning the same, and people who want a type name suited for display will explicitly ask for one It is the less risky/disruptive choice - and it should eventually make it fairly obvious when someone is asking for the wrong type Caveats: - for now, GetDisplayTypeName() == GetTypeName(), there is no logic to produce customized display type names yet. - while the fully-qualified type name is still the main key to the kingdom of data formatters, if we start showing custom names to people, those should match formatters llvm-svn: 209072
2014-05-17 19:14:17 +00:00
}
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) {
ExecutionContext exe_ctx(GetExecutionContextRef());
auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
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);
}