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

438 lines
10 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"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
#pragma mark ValueObjectRegisterContext
ValueObjectRegisterContext::ValueObjectRegisterContext (ValueObject &parent, RegisterContextSP &reg_ctx) :
Fixed an expression parsing issue where if you were stopped somewhere without debug information and you evaluated an expression, a crash would occur as a result of an unchecked pointer. Added the ability to get the expression path for a ValueObject. For a rectangle point child "x" the expression path would be something like: "rect.top_left.x". This will allow GUI and command lines to get ahold of the expression path for a value object without having to explicitly know about the hierarchy. This means the ValueObject base class now has a "ValueObject *m_parent;" member. All ValueObject subclasses now correctly track their lineage and are able to provide value expression paths as well. Added a new "--flat" option to the "frame variable" to allow for flat variable output. An example of the current and new outputs: (lldb) frame variable argc = 1 argv = 0x00007fff5fbffe80 pt = { x = 2 y = 3 } rect = { bottom_left = { x = 1 y = 2 } top_right = { x = 3 y = 4 } } (lldb) frame variable --flat argc = 1 argv = 0x00007fff5fbffe80 pt.x = 2 pt.y = 3 rect.bottom_left.x = 1 rect.bottom_left.y = 2 rect.top_right.x = 3 rect.top_right.y = 4 As you can see when there is a lot of hierarchy it can help flatten things out. Also if you want to use a member in an expression, you can copy the text from the "--flat" output and not have to piece it together manually. This can help when you want to use parts of the STL in expressions: (lldb) frame variable --flat argc = 1 argv = 0x00007fff5fbffea8 hello_world._M_dataplus._M_p = 0x0000000000000000 (lldb) expr hello_world._M_dataplus._M_p[0] == '\0' llvm-svn: 116532
2010-10-14 22:52:14 +00:00
ValueObject (parent),
m_reg_ctx_sp (reg_ctx)
{
assert (reg_ctx);
m_name.SetCString("Registers");
SetValueIsValid (true);
}
ValueObjectRegisterContext::~ValueObjectRegisterContext()
{
}
ClangASTType
ValueObjectRegisterContext::GetClangTypeImpl ()
{
return ClangASTType();
}
ConstString
ValueObjectRegisterContext::GetTypeName()
{
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::GetDisplayTypeName()
{
return ConstString();
}
ConstString
ValueObjectRegisterContext::GetQualifiedTypeName()
{
return ConstString();
}
size_t
ValueObjectRegisterContext::CalculateNumChildren()
{
return m_reg_ctx_sp->GetRegisterSetCount();
}
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()
{
}
ClangASTType
ValueObjectRegisterSet::GetClangTypeImpl ()
{
return ClangASTType();
}
ConstString
ValueObjectRegisterSet::GetTypeName()
{
return ConstString();
}
ConstString
ValueObjectRegisterSet::GetQualifiedTypeName()
{
return ConstString();
}
size_t
ValueObjectRegisterSet::CalculateNumChildren()
{
const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
if (reg_set)
return reg_set->num_registers;
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
2011-05-09 20:18:18 +00:00
ValueObjectRegister::ConstructObject (uint32_t reg_num)
{
2011-05-09 20:18:18 +00:00
const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex (reg_num);
if (reg_info)
{
2011-05-09 20:18:18 +00:00
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);
}
}
2011-05-09 20:18:18 +00:00
ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP &reg_ctx_sp, uint32_t reg_num) :
ValueObject (parent),
2011-05-09 20:18:18 +00:00
m_reg_ctx_sp (reg_ctx_sp),
m_reg_info (),
m_reg_value (),
m_type_name (),
m_clang_type ()
{
2011-05-09 20:18:18 +00:00
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),
2011-05-09 20:18:18 +00:00
m_reg_info (),
m_reg_value (),
m_type_name (),
m_clang_type ()
{
assert (reg_ctx);
2011-05-09 20:18:18 +00:00
ConstructObject(reg_num);
}
ValueObjectRegister::~ValueObjectRegister()
{
}
ClangASTType
ValueObjectRegister::GetClangTypeImpl ()
{
if (!m_clang_type.IsValid())
{
ExecutionContext exe_ctx (GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
if (target)
{
Module *exe_module = target->GetExecutableModulePointer();
if (exe_module)
{
2011-05-09 20:18:18 +00:00
m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
m_reg_info.byte_size * 8);
}
}
}
return m_clang_type;
}
ConstString
ValueObjectRegister::GetTypeName()
{
if (m_type_name.IsEmpty())
m_type_name = GetClangType().GetConstTypeName ();
return m_type_name;
}
size_t
ValueObjectRegister::CalculateNumChildren()
{
return GetClangType().GetNumChildren(true);
}
uint64_t
ValueObjectRegister::GetByteSize()
{
2011-05-09 20:18:18 +00:00
return m_reg_info.byte_size;
}
bool
ValueObjectRegister::UpdateValue ()
{
m_error.Clear();
ExecutionContext exe_ctx(GetExecutionContextRef());
StackFrame *frame = exe_ctx.GetFramePtr();
2011-05-09 20:18:18 +00:00
if (frame == NULL)
{
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)
{
2011-05-09 20:18:18 +00:00
if (m_reg_ctx_sp->ReadRegister (&m_reg_info, m_reg_value))
{
2011-05-09 20:18:18 +00:00
if (m_reg_value.GetData (m_data))
{
Process *process = exe_ctx.GetProcessPtr();
if (process)
m_data.SetAddressByteSize(process->GetAddressByteSize());
2011-05-09 20:18:18 +00:00
m_value.SetContext(Value::eContextTypeRegisterInfo, (void *)&m_reg_info);
m_value.SetValueType(Value::eValueTypeHostAddress);
m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
SetValueIsValid (true);
return true;
}
}
}
SetValueIsValid (false);
m_error.SetErrorToGenericError ();
return false;
}
bool
ValueObjectRegister::SetValueFromCString (const char *value_str, Error& error)
{
// The new value will be in the m_data. Copy that into our register value.
error = m_reg_value.SetValueFromCString (&m_reg_info, 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, Error &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);
}