forked from OSchip/llvm-project
Extended the IR interpreter to handle the variables
"_cmd", "this", and "self". These variables are handled differently from all other external variables used by the expression. Other variables are used indirectly through the $__lldb_arg operand; only _cmd, this, and self are passed directly through the ABI. There are two modifications: - I added a function to ClangExpressionDeclMap that retrives the value of one of these variables by name; and - I made IRInterpreter fetch these values when needed, and ensured that the proper level of indirection is used. llvm-svn: 143065
This commit is contained in:
parent
b3285224cd
commit
d2cb626ac1
|
@ -440,6 +440,19 @@ public:
|
|||
lldb_private::Value
|
||||
LookupDecl (clang::NamedDecl *decl);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Used by IRInterpreter] Get the Value for "this", "self", or
|
||||
/// "_cmd".
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The name of the entity to be found.
|
||||
///
|
||||
/// @return
|
||||
/// The value, or NULL.
|
||||
//------------------------------------------------------------------
|
||||
lldb_private::Value
|
||||
GetSpecialValue (const ConstString &name);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Used by IRInterpreter] Returns true if the result is a
|
||||
/// reference to data in the target, meaning it must be
|
||||
|
|
|
@ -959,7 +959,12 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
|
|||
if (!expr_var_sp->m_parser_vars.get() || !expr_var_sp->m_parser_vars->m_lldb_var)
|
||||
return Value();
|
||||
|
||||
return *GetVariableValue(exe_ctx, expr_var_sp->m_parser_vars->m_lldb_var, NULL);
|
||||
std::auto_ptr<Value> value(GetVariableValue(exe_ctx, expr_var_sp->m_parser_vars->m_lldb_var, NULL));
|
||||
|
||||
if (value.get())
|
||||
return *value;
|
||||
else
|
||||
return Value();
|
||||
}
|
||||
else if (persistent_var_sp)
|
||||
{
|
||||
|
@ -969,7 +974,7 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
|
|||
m_parser_vars->m_exe_ctx->GetProcessSP() &&
|
||||
m_parser_vars->m_exe_ctx->GetProcessSP()->IsAlive())
|
||||
{
|
||||
return persistent_var_sp->m_live_sp->GetValue();
|
||||
return persistent_var_sp->m_live_sp->GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -986,6 +991,39 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
|
|||
}
|
||||
}
|
||||
|
||||
Value
|
||||
ClangExpressionDeclMap::GetSpecialValue (const ConstString &name)
|
||||
{
|
||||
assert(m_parser_vars.get());
|
||||
|
||||
if (!m_parser_vars->m_exe_ctx)
|
||||
return Value();
|
||||
|
||||
StackFrame *frame = m_parser_vars->m_exe_ctx->GetFramePtr();
|
||||
|
||||
if (!frame)
|
||||
return Value();
|
||||
|
||||
VariableList *vars = frame->GetVariableList(false);
|
||||
|
||||
if (!vars)
|
||||
return Value();
|
||||
|
||||
lldb::VariableSP var = vars->FindVariable(name);
|
||||
|
||||
if (!var ||
|
||||
!var->IsInScope(frame) ||
|
||||
!var->LocationIsValidForFrame (frame))
|
||||
return Value();
|
||||
|
||||
std::auto_ptr<Value> value(GetVariableValue(*m_parser_vars->m_exe_ctx, var, NULL));
|
||||
|
||||
if (value.get())
|
||||
return *value;
|
||||
else
|
||||
return Value();
|
||||
}
|
||||
|
||||
// Interface for CommandObjectExpression
|
||||
|
||||
bool
|
||||
|
@ -1535,8 +1573,8 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
Error allocate_error;
|
||||
|
||||
mem = process->AllocateMemory(pvar_byte_size,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
allocate_error);
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
allocate_error);
|
||||
|
||||
if (mem == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
|
@ -1577,9 +1615,9 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
// Now write the location of the area into the struct.
|
||||
Error write_error;
|
||||
if (!process->WriteScalarToMemory (addr,
|
||||
var_sp->m_live_sp->GetValue().GetScalar(),
|
||||
process->GetAddressByteSize(),
|
||||
write_error))
|
||||
var_sp->m_live_sp->GetValue().GetScalar(),
|
||||
process->GetAddressByteSize(),
|
||||
write_error))
|
||||
{
|
||||
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
|
||||
return false;
|
||||
|
|
|
@ -576,6 +576,12 @@ public:
|
|||
|
||||
const GlobalValue *global_value = dyn_cast<GlobalValue>(value);
|
||||
|
||||
// If the variable is indirected through the argument
|
||||
// array then we need to build an extra level of indirection
|
||||
// for it. This is the default; only magic arguments like
|
||||
// "this", "self", and "_cmd" are direct.
|
||||
bool indirect_variable = true;
|
||||
|
||||
// Attempt to resolve the value using the program's data.
|
||||
// If it is, the values to be created are:
|
||||
//
|
||||
|
@ -586,17 +592,40 @@ public:
|
|||
// resides. This is an IR-level variable.
|
||||
do
|
||||
{
|
||||
if (!global_value)
|
||||
break;
|
||||
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
lldb_private::Value resolved_value;
|
||||
|
||||
clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
|
||||
|
||||
if (!decl)
|
||||
break;
|
||||
|
||||
lldb_private::Value resolved_value = m_decl_map.LookupDecl(decl);
|
||||
if (global_value)
|
||||
{
|
||||
clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
|
||||
|
||||
if (!decl)
|
||||
break;
|
||||
|
||||
if (isa<clang::FunctionDecl>(decl))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("The interpreter does not handle function pointers at the moment");
|
||||
|
||||
return Memory::Region();
|
||||
}
|
||||
|
||||
resolved_value = m_decl_map.LookupDecl(decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special-case "this", "self", and "_cmd"
|
||||
|
||||
std::string name_str = value->getNameStr();
|
||||
|
||||
if (name_str == "this" ||
|
||||
name_str == "self" ||
|
||||
name_str == "_cmd")
|
||||
resolved_value = m_decl_map.GetSpecialValue(lldb_private::ConstString(name_str.c_str()));
|
||||
|
||||
indirect_variable = false;
|
||||
}
|
||||
|
||||
if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void)
|
||||
{
|
||||
|
@ -605,7 +634,10 @@ public:
|
|||
Memory::Region data_region = m_memory.Malloc(value->getType());
|
||||
data_region.m_allocation->m_origin = resolved_value;
|
||||
Memory::Region ref_region = m_memory.Malloc(value->getType());
|
||||
Memory::Region pointer_region = m_memory.Malloc(value->getType());
|
||||
Memory::Region pointer_region;
|
||||
|
||||
if (indirect_variable)
|
||||
pointer_region = m_memory.Malloc(value->getType());
|
||||
|
||||
if (!Cache(data_region.m_allocation, value->getType()))
|
||||
return Memory::Region();
|
||||
|
@ -613,7 +645,7 @@ public:
|
|||
if (ref_region.IsInvalid())
|
||||
return Memory::Region();
|
||||
|
||||
if (pointer_region.IsInvalid())
|
||||
if (pointer_region.IsInvalid() && indirect_variable)
|
||||
return Memory::Region();
|
||||
|
||||
DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
|
||||
|
@ -621,31 +653,35 @@ public:
|
|||
if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
|
||||
|
||||
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
m_values[value] = pointer_region;
|
||||
return pointer_region;
|
||||
}
|
||||
else if (isa<clang::FunctionDecl>(decl))
|
||||
{
|
||||
if (log)
|
||||
log->Printf("The interpreter does not handle function pointers at the moment");
|
||||
|
||||
return Memory::Region();
|
||||
if (indirect_variable)
|
||||
{
|
||||
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
|
||||
|
||||
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
m_values[value] = pointer_region;
|
||||
return pointer_region;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_values[value] = ref_region;
|
||||
return ref_region;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value);
|
||||
Memory::Region ref_region = m_memory.Malloc(value->getType());
|
||||
Memory::Region pointer_region = m_memory.Malloc(value->getType());
|
||||
Memory::Region pointer_region;
|
||||
|
||||
if (indirect_variable)
|
||||
pointer_region = m_memory.Malloc(value->getType());
|
||||
|
||||
if (ref_region.IsInvalid())
|
||||
return Memory::Region();
|
||||
|
||||
if (pointer_region.IsInvalid())
|
||||
if (pointer_region.IsInvalid() && indirect_variable)
|
||||
return Memory::Region();
|
||||
|
||||
DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
|
||||
|
@ -653,23 +689,30 @@ public:
|
|||
if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
|
||||
if (indirect_variable)
|
||||
{
|
||||
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
|
||||
|
||||
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
m_values[value] = pointer_region;
|
||||
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
|
||||
return Memory::Region();
|
||||
|
||||
m_values[value] = pointer_region;
|
||||
}
|
||||
|
||||
if (log)
|
||||
{
|
||||
log->Printf("Made an allocation for %s", PrintValue(global_value).c_str());
|
||||
log->Printf("Made an allocation for %s", PrintValue(value).c_str());
|
||||
log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
|
||||
log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base);
|
||||
log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base);
|
||||
log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
|
||||
if (indirect_variable)
|
||||
log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
|
||||
}
|
||||
|
||||
return pointer_region;
|
||||
if (indirect_variable)
|
||||
return pointer_region;
|
||||
else
|
||||
return ref_region;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue