forked from OSchip/llvm-project
Added a feature where registers can be referred to
using special $-variables from expressions. (lldb) expr $rip These variables are available for reading and writing. llvm-svn: 120367
This commit is contained in:
parent
027bd47e3e
commit
348b5897f9
|
@ -489,6 +489,18 @@ private:
|
|||
//------------------------------------------------------------------
|
||||
void AddOneFunction(NameSearchContext &context, Function *fun, Symbol *sym);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Use the NameSearchContext to generate a Decl for the given
|
||||
/// register.
|
||||
///
|
||||
/// @param[in] context
|
||||
/// The NameSearchContext to use when constructing the Decl.
|
||||
///
|
||||
/// @param[in] reg_info
|
||||
/// The information corresponding to that register.
|
||||
//------------------------------------------------------------------
|
||||
void AddOneRegister(NameSearchContext &context, const lldb::RegisterInfo *reg_info);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Use the NameSearchContext to generate a Decl for the given
|
||||
/// type. (Types are not placed in the Tuple list.)
|
||||
|
@ -604,6 +616,40 @@ private:
|
|||
lldb::addr_t addr,
|
||||
Error &err);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Actually do the task of materializing or dematerializing a
|
||||
/// register variable.
|
||||
///
|
||||
/// @param[in] dematerialize
|
||||
/// True if the variable is to be dematerialized; false if it is to
|
||||
/// be materialized.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to use.
|
||||
///
|
||||
/// @param[in] reg_ctx
|
||||
/// The register context to use.
|
||||
///
|
||||
/// @param[in] reg_info
|
||||
/// The information for the register to read/write.
|
||||
///
|
||||
/// @param[in] addr
|
||||
/// The address at which to materialize the variable.
|
||||
///
|
||||
/// @param[in] err
|
||||
/// An Error to populate with any messages related to
|
||||
/// (de)materializing the persistent variable.
|
||||
///
|
||||
/// @return
|
||||
/// True on success; false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool DoMaterializeOneRegister(bool dematerialize,
|
||||
ExecutionContext &exe_ctx,
|
||||
RegisterContext ®_ctx,
|
||||
const lldb::RegisterInfo ®_info,
|
||||
lldb::addr_t addr,
|
||||
Error &err);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// A wrapper for ClangASTContext::CopyType that sets a flag that
|
||||
/// indicates that we should not respond to queries during import.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-types.h"
|
||||
#include "lldb/Core/ClangForward.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Symbol/TaggedASTType.h"
|
||||
|
@ -89,9 +90,11 @@ struct ClangExpressionVariable
|
|||
//----------------------------------------------------------------------
|
||||
/// The following values should stay valid for the life of the variable
|
||||
//----------------------------------------------------------------------
|
||||
ConstString m_name; ///< The name of the variable
|
||||
TypeFromUser m_user_type; ///< The type of the variable according to some LLDB context;
|
||||
///< NULL if the type hasn't yet been migrated to one
|
||||
ConstString m_name; ///< The name of the variable
|
||||
TypeFromUser m_user_type; ///< The type of the variable according to some LLDB context;
|
||||
///< NULL if the type hasn't yet been migrated to one
|
||||
|
||||
const lldb::RegisterInfo *m_register_info; ///< if non-NULL, LLDB's information for the register this value is stored in. Only used for register values
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// The following values indicate where the variable originally came from
|
||||
|
|
|
@ -132,6 +132,8 @@ clang::ASTContext *NameSearchContext::GetASTContext() {
|
|||
|
||||
clang::NamedDecl *NameSearchContext::AddVarDecl(void *type) {
|
||||
IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
|
||||
|
||||
assert (type && "Type for variable must be non-NULL!");
|
||||
|
||||
clang::NamedDecl *Decl = VarDecl::Create(m_ast_source.m_ast_context,
|
||||
const_cast<DeclContext*>(m_decl_context),
|
||||
|
|
|
@ -584,11 +584,26 @@ ClangExpressionDeclMap::DoMaterialize
|
|||
|
||||
if (entity)
|
||||
{
|
||||
if (!member.m_jit_vars.get())
|
||||
return false;
|
||||
|
||||
if (!DoMaterializeOneVariable(dematerialize, *exe_ctx, sym_ctx, member.m_name, member.m_user_type, m_materialized_location + member.m_jit_vars->m_offset, err))
|
||||
return false;
|
||||
if (entity->m_register_info)
|
||||
{
|
||||
// This is a register variable
|
||||
|
||||
RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
|
||||
|
||||
if (!reg_ctx)
|
||||
return false;
|
||||
|
||||
if (!DoMaterializeOneRegister(dematerialize, *exe_ctx, *reg_ctx, *entity->m_register_info, m_materialized_location + member.m_jit_vars->m_offset, err))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!member.m_jit_vars.get())
|
||||
return false;
|
||||
|
||||
if (!DoMaterializeOneVariable(dematerialize, *exe_ctx, sym_ctx, member.m_name, member.m_user_type, m_materialized_location + member.m_jit_vars->m_offset, err))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (persistent_variable)
|
||||
{
|
||||
|
@ -917,6 +932,72 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangExpressionDeclMap::DoMaterializeOneRegister
|
||||
(
|
||||
bool dematerialize,
|
||||
ExecutionContext &exe_ctx,
|
||||
RegisterContext ®_ctx,
|
||||
const lldb::RegisterInfo ®_info,
|
||||
lldb::addr_t addr,
|
||||
Error &err
|
||||
)
|
||||
{
|
||||
uint32_t register_number = reg_info.kinds[lldb::eRegisterKindLLDB];
|
||||
uint32_t register_byte_size = reg_info.byte_size;
|
||||
|
||||
Error error;
|
||||
|
||||
if (dematerialize)
|
||||
{
|
||||
DataBufferHeap register_data (register_byte_size, 0);
|
||||
|
||||
Error error;
|
||||
if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes(), register_byte_size, error) != register_byte_size)
|
||||
{
|
||||
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", reg_info.name, error.AsCString());
|
||||
return false;
|
||||
}
|
||||
|
||||
DataExtractor register_extractor (register_data.GetBytes(), register_byte_size, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
|
||||
|
||||
if (!reg_ctx.WriteRegisterBytes(register_number, register_extractor, 0))
|
||||
{
|
||||
err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DataExtractor register_extractor;
|
||||
|
||||
if (!reg_ctx.ReadRegisterBytes(register_number, register_extractor))
|
||||
{
|
||||
err.SetErrorStringWithFormat("Couldn't read %s", reg_info.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t register_offset = 0;
|
||||
|
||||
const void *register_data = register_extractor.GetData(®ister_offset, register_byte_size);
|
||||
|
||||
if (!register_data)
|
||||
{
|
||||
err.SetErrorStringWithFormat("Read but couldn't extract data for %s", reg_info.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
Error error;
|
||||
if (exe_ctx.process->WriteMemory (addr, register_data, register_byte_size, error) != register_byte_size)
|
||||
{
|
||||
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Variable *
|
||||
ClangExpressionDeclMap::FindVariableInScope
|
||||
(
|
||||
|
@ -1121,7 +1202,20 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
|
|||
ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
|
||||
|
||||
if (pvar)
|
||||
{
|
||||
AddOneVariable(context, pvar);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *reg_name(&name.GetCString()[1]);
|
||||
|
||||
if (m_exe_ctx.GetRegisterContext())
|
||||
{
|
||||
const lldb::RegisterInfo *reg_info(m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name));
|
||||
|
||||
if (reg_info)
|
||||
AddOneRegister(context, reg_info);
|
||||
}
|
||||
}
|
||||
|
||||
lldb::TypeSP type_sp (m_sym_ctx.FindTypeByName (name));
|
||||
|
@ -1338,6 +1432,49 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
|
||||
const RegisterInfo *reg_info)
|
||||
{
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
void *ast_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(context.GetASTContext(),
|
||||
reg_info->encoding,
|
||||
reg_info->byte_size * 8);
|
||||
|
||||
if (!ast_type)
|
||||
{
|
||||
log->Printf("Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
TypeFromParser parser_type(ast_type,
|
||||
context.GetASTContext());
|
||||
|
||||
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
|
||||
|
||||
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(m_found_entities.CreateVariable()));
|
||||
std::string decl_name(context.m_decl_name.getAsString());
|
||||
entity.m_name.SetCString (decl_name.c_str());
|
||||
entity.m_register_info = reg_info;
|
||||
|
||||
entity.EnableParserVars();
|
||||
entity.m_parser_vars->m_parser_type = parser_type;
|
||||
entity.m_parser_vars->m_named_decl = var_decl;
|
||||
entity.m_parser_vars->m_llvm_value = NULL;
|
||||
entity.m_parser_vars->m_lldb_value = NULL;
|
||||
|
||||
if (log)
|
||||
{
|
||||
std::string var_decl_print_string;
|
||||
llvm::raw_string_ostream var_decl_print_stream(var_decl_print_string);
|
||||
var_decl->print(var_decl_print_stream);
|
||||
var_decl_print_stream.flush();
|
||||
|
||||
log->Printf("Added register %s, returned %s", context.m_decl_name.getAsString().c_str(), var_decl_print_string.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
clang::NamespaceDecl *
|
||||
ClangExpressionDeclMap::AddNamespace (NameSearchContext &context, const ClangNamespaceDecl &namespace_decl)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ ClangExpressionVariable::ClangExpressionVariable() :
|
|||
m_name(),
|
||||
m_user_type (TypeFromUser(NULL, NULL)),
|
||||
m_store (NULL),
|
||||
m_register_info (NULL),
|
||||
m_index (0),
|
||||
m_parser_vars(),
|
||||
m_jit_vars (),
|
||||
|
|
Loading…
Reference in New Issue