mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-05-15 02:16:40 +00:00

defines a protocol that all subclasses will implement. StackFrame is currently the only subclass and the methods that Frame vends are nearly identical to StackFrame's old methods. Update all callers to use Frame*/Frame& instead of pointers to StackFrames. This is almost entirely a mechanical change that touches a lot of the code base so I'm committing it alone. No new functionality is added with this patch, no new subclasses of Frame exist yet. I'll probably need to tweak some of the separation, possibly moving some of StackFrame's methods up in to Frame, but this is a good starting point. <rdar://problem/15314068> llvm-svn: 193907
432 lines
10 KiB
C++
432 lines
10 KiB
C++
//===-- 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 ®_ctx) :
|
|
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();
|
|
}
|
|
|
|
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());
|
|
Frame *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 ®_ctx_sp, uint32_t set_idx)
|
|
{
|
|
return (new ValueObjectRegisterSet (exe_scope, reg_ctx_sp, set_idx))->GetSP();
|
|
}
|
|
|
|
|
|
ValueObjectRegisterSet::ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_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());
|
|
Frame *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 ®_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_clang_type ()
|
|
{
|
|
assert (reg_ctx_sp.get());
|
|
ConstructObject(reg_num);
|
|
}
|
|
|
|
ValueObjectSP
|
|
ValueObjectRegister::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num)
|
|
{
|
|
return (new ValueObjectRegister (exe_scope, reg_ctx_sp, reg_num))->GetSP();
|
|
}
|
|
|
|
ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_num) :
|
|
ValueObject (exe_scope),
|
|
m_reg_ctx_sp (reg_ctx),
|
|
m_reg_info (),
|
|
m_reg_value (),
|
|
m_type_name (),
|
|
m_clang_type ()
|
|
{
|
|
assert (reg_ctx);
|
|
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)
|
|
{
|
|
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()
|
|
{
|
|
return m_reg_info.byte_size;
|
|
}
|
|
|
|
bool
|
|
ValueObjectRegister::UpdateValue ()
|
|
{
|
|
m_error.Clear();
|
|
ExecutionContext exe_ctx(GetExecutionContextRef());
|
|
Frame *frame = exe_ctx.GetFramePtr();
|
|
if (frame == NULL)
|
|
{
|
|
m_reg_ctx_sp.reset();
|
|
m_reg_value.Clear();
|
|
}
|
|
|
|
|
|
if (m_reg_ctx_sp)
|
|
{
|
|
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);
|
|
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);
|
|
}
|
|
|
|
|