Fixed object lifetimes in ClangExpressionDeclMap

so that it is not referring to potentially stale
state during IR execution.

This was done by introducing modular state (like
ClangExpressionVariable) where groups of state
variables have well-defined lifetimes:

- m_parser_vars are specific to parsing, and only
  exist between calls to WillParse() and DidParse().

- m_struct_vars survive for the entire execution
  of the ClangExpressionDeclMap because they
  provide the template for a materialized set of
  expression variables.

- m_material_vars are specific to a single
  instance of materialization, and only exist
  between calls to Materialize() and
  Dematerialize().

I also removed unnecessary references to long-
lived state that really didn't need to be referred
to at all, and also introduced several assert()s
that helped me diagnose a few bugs (fixed too).

llvm-svn: 120778
This commit is contained in:
Sean Callanan 2010-12-03 01:38:59 +00:00
parent a41772aa0f
commit 979f74d1dd
5 changed files with 386 additions and 192 deletions

View File

@ -71,18 +71,28 @@ public:
/// Constructor
///
/// Initializes class variabes.
///
/// @param[in] exe_ctx
/// The execution context to use when finding types for variables.
/// Also used to find a "scratch" AST context to store result types.
//------------------------------------------------------------------
ClangExpressionDeclMap(ExecutionContext *exe_ctx);
ClangExpressionDeclMap();
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
~ClangExpressionDeclMap();
//------------------------------------------------------------------
/// Enable the state needed for parsing and IR transformation.
///
/// @param[in] exe_ctx
/// The execution context to use when finding types for variables.
/// Also used to find a "scratch" AST context to store result types.
//------------------------------------------------------------------
void WillParse(ExecutionContext &exe_ctx);
//------------------------------------------------------------------
/// Disable the state needed for parsing and IR transformation.
//------------------------------------------------------------------
void DidParse();
//------------------------------------------------------------------
/// [Used by IRForTarget] Get a new result variable name of the form
/// $n, where n is a natural number starting with 0.
@ -270,7 +280,7 @@ public:
/// @return
/// True on success; false otherwise.
//------------------------------------------------------------------
bool Materialize(ExecutionContext *exe_ctx,
bool Materialize(ExecutionContext &exe_ctx,
lldb::addr_t &struct_address,
Error &error);
@ -292,7 +302,7 @@ public:
/// True on success; false otherwise.
//------------------------------------------------------------------
bool GetObjectPointer(lldb::addr_t &object_ptr,
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
Error &error);
//------------------------------------------------------------------
@ -313,7 +323,7 @@ public:
/// @return
/// True on success; false otherwise.
//------------------------------------------------------------------
bool DumpMaterializedStruct(ExecutionContext *exe_ctx,
bool DumpMaterializedStruct(ExecutionContext &exe_ctx,
Stream &s,
Error &error);
@ -334,7 +344,7 @@ public:
/// @return
/// True on success; false otherwise.
//------------------------------------------------------------------
bool Dematerialize(ExecutionContext *exe_ctx,
bool Dematerialize(ExecutionContext &exe_ctx,
ClangExpressionVariable *&result,
Error &error);
@ -356,37 +366,153 @@ public:
//------------------------------------------------------------------
void GetDecls (NameSearchContext &context,
const ConstString &name);
//------------------------------------------------------------------
/// [Used by ClangASTSource] Report whether a $__lldb variable has
/// been searched for yet. This is the trigger for beginning to
/// actually look for externally-defined names. (Names that come
/// before this are typically the names of built-ins that don't need
/// to be looked up.)
///
/// @return
/// True if a $__lldb variable has been found.
//------------------------------------------------------------------
bool
GetLookupsEnabled ()
{
return m_enable_lookups;
assert(m_parser_vars.get());
return m_parser_vars->m_enable_lookups;
}
//------------------------------------------------------------------
/// [Used by ClangASTSource] Indicate that a $__lldb variable has
/// been found.
//------------------------------------------------------------------
void
SetLookupsEnabled (bool b)
SetLookupsEnabled ()
{
m_enable_lookups = b;
assert(m_parser_vars.get());
m_parser_vars->m_enable_lookups = true;
}
private:
ClangExpressionVariableStore m_found_entities; ///< All entities that were looked up for the parser.
ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
ClangExpressionVariableStore m_found_entities; ///< All entities that were looked up for the parser.
ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
ExecutionContext m_exe_ctx; ///< The execution context where this expression was first defined. It determines types for all the external variables, even if the expression is re-used.
SymbolContext m_sym_ctx; ///< [owned by ClangExpressionDeclMap] The symbol context where this expression was first defined.
ClangPersistentVariables *m_persistent_vars; ///< The list of persistent variables to use when resolving symbols in the expression and when creating new ones (like the result).
off_t m_struct_alignment; ///< The alignment of the struct in bytes.
size_t m_struct_size; ///< The size of the struct in bytes.
bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since).
bool m_enable_lookups; ///< Set to true during expression evaluation if we have found the first "$__lldb" name.
lldb::addr_t m_allocated_area; ///< The base of the memory allocated for the struct. Starts on a potentially unaligned address and may therefore be larger than the struct.
lldb::addr_t m_materialized_location; ///< The address at which the struct is placed. Falls inside the allocated area.
ConstString m_result_name; ///< The name of the result variable ($1, for example)
TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists.
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
//----------------------------------------------------------------------
struct ParserVars {
ParserVars() :
m_exe_ctx(NULL),
m_sym_ctx(),
m_persistent_vars(NULL),
m_enable_lookups(false),
m_ignore_lookups(false)
{
}
ExecutionContext *m_exe_ctx; ///< The execution context to use when parsing.
SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types.
ClangPersistentVariables *m_persistent_vars; ///< The persistent variables for the process.
bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name.
bool m_ignore_lookups; ///< True during an import when we should be ignoring type lookups.
};
std::auto_ptr<ParserVars> m_parser_vars;
//----------------------------------------------------------------------
/// Activate parser-specific variables
//----------------------------------------------------------------------
void EnableParserVars()
{
if (!m_parser_vars.get())
m_parser_vars.reset(new struct ParserVars);
}
//----------------------------------------------------------------------
/// Deallocate parser-specific variables
//----------------------------------------------------------------------
void DisableParserVars()
{
m_parser_vars.reset();
}
//----------------------------------------------------------------------
/// The following values contain layout information for the materialized
/// struct, but are not specific to a single materialization
//----------------------------------------------------------------------
struct StructVars {
StructVars() :
m_struct_alignment(0),
m_struct_size(0),
m_struct_laid_out(false),
m_result_name(),
m_object_pointer_type(NULL, NULL)
{
}
off_t m_struct_alignment; ///< The alignment of the struct in bytes.
size_t m_struct_size; ///< The size of the struct in bytes.
bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since).
ConstString m_result_name; ///< The name of the result variable ($1, for example)
TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists
};
std::auto_ptr<StructVars> m_struct_vars;
//----------------------------------------------------------------------
/// Activate struct variables
//----------------------------------------------------------------------
void EnableStructVars()
{
if (!m_struct_vars.get())
m_struct_vars.reset(new struct StructVars);
}
//----------------------------------------------------------------------
/// Deallocate struct variables
//----------------------------------------------------------------------
void DisableStructVars()
{
m_struct_vars.reset();
}
//----------------------------------------------------------------------
/// The following values refer to a specific materialization of the
/// structure in a process
//----------------------------------------------------------------------
struct MaterialVars {
MaterialVars() :
m_allocated_area(NULL),
m_materialized_location(NULL)
{
}
Process *m_process; ///< The process that the struct is materialized into.
lldb::addr_t m_allocated_area; ///< The base of the memory allocated for the struct. Starts on a potentially unaligned address and may therefore be larger than the struct.
lldb::addr_t m_materialized_location; ///< The address at which the struct is placed. Falls inside the allocated area.
};
std::auto_ptr<MaterialVars> m_material_vars;
//----------------------------------------------------------------------
/// Activate materialization-specific variables
//----------------------------------------------------------------------
void EnableMaterialVars()
{
if (!m_material_vars.get())
m_material_vars.reset(new struct MaterialVars);
}
//----------------------------------------------------------------------
/// Deallocate materialization-specific variables
//----------------------------------------------------------------------
void DisableMaterialVars()
{
m_material_vars.reset();
}
bool m_ignore_lookups; ///< True during an import when we should be ignoring type lookups.
//------------------------------------------------------------------
/// Given a stack frame, find a variable that matches the given name and
/// type. We need this for expression re-use; we may not always get the
@ -544,9 +670,14 @@ private:
/// True on success; false otherwise.
//------------------------------------------------------------------
bool DoMaterialize (bool dematerialize,
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
ClangExpressionVariable **result,
Error &err);
//------------------------------------------------------------------
/// Clean up the state required to dematerialize the variable.
//------------------------------------------------------------------
void DidDematerialize ();
//------------------------------------------------------------------
/// Actually do the task of materializing or dematerializing a persistent

View File

@ -83,7 +83,7 @@ DeclContext::lookup_result ClangASTSource::FindExternalVisibleDeclsByName
// any lookups so we can avoid lookup up all of the builtin types.
if (!decl_name.empty() && decl_name[0] == '$')
{
m_decl_map.SetLookupsEnabled (true);
m_decl_map.SetLookupsEnabled ();
}
else
{

View File

@ -43,62 +43,58 @@ using namespace lldb;
using namespace lldb_private;
using namespace clang;
ClangExpressionDeclMap::ClangExpressionDeclMap (ExecutionContext *exe_ctx) :
ClangExpressionDeclMap::ClangExpressionDeclMap () :
m_found_entities (),
m_struct_members (),
m_exe_ctx (),
m_sym_ctx (),
m_persistent_vars (NULL),
m_struct_alignment (0),
m_struct_size (0),
m_struct_laid_out (false),
m_enable_lookups (false),
m_allocated_area (0),
m_materialized_location (0),
m_result_name (),
m_object_pointer_type (),
m_ignore_lookups (false)
m_parser_vars (),
m_struct_vars ()
{
if (exe_ctx)
{
m_exe_ctx = *exe_ctx;
if (exe_ctx->frame)
m_sym_ctx = exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything);
if (exe_ctx->process)
m_persistent_vars = &exe_ctx->process->GetPersistentVariables();
}
EnableStructVars();
}
ClangExpressionDeclMap::~ClangExpressionDeclMap()
{
for (uint64_t entity_index = 0, num_entities = m_found_entities.Size();
entity_index < num_entities;
++entity_index)
{
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(entity_index));
if (entity.m_parser_vars.get() &&
entity.m_parser_vars->m_lldb_value)
delete entity.m_parser_vars->m_lldb_value;
entity.DisableParserVars();
}
for (uint64_t pvar_index = 0, num_pvars = m_persistent_vars->Size();
pvar_index < num_pvars;
++pvar_index)
{
ClangExpressionVariable &pvar(m_persistent_vars->VariableAtIndex(pvar_index));
pvar.DisableParserVars();
}
if (m_materialized_location)
{
//#define SINGLE_STEP_EXPRESSIONS
{
DidDematerialize();
DisableStructVars();
}
#ifndef SINGLE_STEP_EXPRESSIONS
m_exe_ctx.process->DeallocateMemory(m_materialized_location);
#endif
m_materialized_location = 0;
void ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx)
{
EnableParserVars();
m_parser_vars->m_exe_ctx = &exe_ctx;
if (exe_ctx.frame)
m_parser_vars->m_sym_ctx = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything);
if (exe_ctx.process)
m_parser_vars->m_persistent_vars = &exe_ctx.process->GetPersistentVariables();
}
void ClangExpressionDeclMap::DidParse()
{
if (m_parser_vars.get())
{
for (uint64_t entity_index = 0, num_entities = m_found_entities.Size();
entity_index < num_entities;
++entity_index)
{
ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(entity_index));
if (entity.m_parser_vars.get() &&
entity.m_parser_vars->m_lldb_value)
delete entity.m_parser_vars->m_lldb_value;
entity.DisableParserVars();
}
for (uint64_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->Size();
pvar_index < num_pvars;
++pvar_index)
{
ClangExpressionVariable &pvar(m_parser_vars->m_persistent_vars->VariableAtIndex(pvar_index));
pvar.DisableParserVars();
}
DisableParserVars();
}
}
@ -107,9 +103,13 @@ ClangExpressionDeclMap::~ClangExpressionDeclMap()
const ConstString &
ClangExpressionDeclMap::GetPersistentResultName ()
{
if (!m_result_name)
m_persistent_vars->GetNextResultName(m_result_name);
return m_result_name;
assert (m_struct_vars.get());
assert (m_parser_vars.get());
if (!m_struct_vars->m_result_name)
m_parser_vars->m_persistent_vars->GetNextResultName(m_struct_vars->m_result_name);
return m_struct_vars->m_result_name;
}
bool
@ -120,17 +120,19 @@ ClangExpressionDeclMap::AddPersistentVariable
TypeFromParser parser_type
)
{
clang::ASTContext *context(m_exe_ctx.target->GetScratchClangASTContext()->getASTContext());
assert (m_parser_vars.get());
clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
TypeFromUser user_type(ClangASTContext::CopyType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
if (!m_persistent_vars->CreatePersistentVariable (name, user_type))
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (name, user_type))
return false;
ClangExpressionVariable *var = m_persistent_vars->GetVariable(name);
ClangExpressionVariable *var = m_parser_vars->m_persistent_vars->GetVariable(name);
if (!var)
return false;
@ -153,9 +155,12 @@ ClangExpressionDeclMap::AddValueToStruct
off_t alignment
)
{
assert (m_struct_vars.get());
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
m_struct_laid_out = false;
m_struct_vars->m_struct_laid_out = false;
if (m_struct_members.GetVariable(decl))
return true;
@ -163,7 +168,7 @@ ClangExpressionDeclMap::AddValueToStruct
ClangExpressionVariable *var = m_found_entities.GetVariable(decl);
if (!var)
var = m_persistent_vars->GetVariable(decl);
var = m_parser_vars->m_persistent_vars->GetVariable(decl);
if (!var)
return false;
@ -190,13 +195,15 @@ ClangExpressionDeclMap::AddValueToStruct
bool
ClangExpressionDeclMap::DoStructLayout ()
{
if (m_struct_laid_out)
assert (m_struct_vars.get());
if (m_struct_vars->m_struct_laid_out)
return true;
off_t cursor = 0;
m_struct_alignment = 0;
m_struct_size = 0;
m_struct_vars->m_struct_alignment = 0;
m_struct_vars->m_struct_size = 0;
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
member_index < num_members;
@ -208,7 +215,7 @@ ClangExpressionDeclMap::DoStructLayout ()
return false;
if (member_index == 0)
m_struct_alignment = member.m_jit_vars->m_alignment;
m_struct_vars->m_struct_alignment = member.m_jit_vars->m_alignment;
if (cursor % member.m_jit_vars->m_alignment)
cursor += (member.m_jit_vars->m_alignment - (cursor % member.m_jit_vars->m_alignment));
@ -217,9 +224,9 @@ ClangExpressionDeclMap::DoStructLayout ()
cursor += member.m_jit_vars->m_size;
}
m_struct_size = cursor;
m_struct_vars->m_struct_size = cursor;
m_struct_laid_out = true;
m_struct_vars->m_struct_laid_out = true;
return true;
}
@ -230,12 +237,14 @@ bool ClangExpressionDeclMap::GetStructInfo
off_t &alignment
)
{
if (!m_struct_laid_out)
assert (m_struct_vars.get());
if (!m_struct_vars->m_struct_laid_out)
return false;
num_elements = m_struct_members.Size();
size = m_struct_size;
alignment = m_struct_alignment;
size = m_struct_vars->m_struct_size;
alignment = m_struct_vars->m_struct_alignment;
return true;
}
@ -250,7 +259,9 @@ ClangExpressionDeclMap::GetStructElement
uint32_t index
)
{
if (!m_struct_laid_out)
assert (m_struct_vars.get());
if (!m_struct_vars->m_struct_laid_out)
return false;
if (index >= m_struct_members.Size())
@ -299,13 +310,15 @@ ClangExpressionDeclMap::GetFunctionAddress
uint64_t &ptr
)
{
assert (m_parser_vars.get());
// Back out in all cases where we're not fully initialized
if (m_exe_ctx.frame == NULL)
if (m_parser_vars->m_exe_ctx->frame == NULL)
return false;
SymbolContextList sc_list;
m_sym_ctx.FindFunctionsByName(name, false, sc_list);
m_parser_vars->m_sym_ctx.FindFunctionsByName(name, false, sc_list);
if (!sc_list.GetSize())
return false;
@ -322,7 +335,7 @@ ClangExpressionDeclMap::GetFunctionAddress
else
return false;
ptr = fun_address->GetLoadAddress (m_exe_ctx.target);
ptr = fun_address->GetLoadAddress (m_parser_vars->m_exe_ctx->target);
return true;
}
@ -332,15 +345,19 @@ ClangExpressionDeclMap::GetFunctionAddress
bool
ClangExpressionDeclMap::Materialize
(
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
lldb::addr_t &struct_address,
Error &err
)
{
EnableMaterialVars();
m_material_vars->m_process = exe_ctx.process;
bool result = DoMaterialize(false, exe_ctx, NULL, err);
if (result)
struct_address = m_materialized_location;
struct_address = m_material_vars->m_materialized_location;
return result;
}
@ -349,24 +366,26 @@ bool
ClangExpressionDeclMap::GetObjectPointer
(
lldb::addr_t &object_ptr,
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
Error &err
)
{
if (!exe_ctx || !exe_ctx->frame || !exe_ctx->target || !exe_ctx->process)
assert (m_struct_vars.get());
if (!exe_ctx.frame || !exe_ctx.target || !exe_ctx.process)
{
err.SetErrorString("Couldn't load 'this' because the context is incomplete");
return false;
}
if (!m_object_pointer_type.GetOpaqueQualType())
if (!m_struct_vars->m_object_pointer_type.GetOpaqueQualType())
{
err.SetErrorString("Couldn't load 'this' because its type is unknown");
return false;
}
static ConstString g_this_const_str ("this");
Variable *object_ptr_var = FindVariableInScope (*exe_ctx->frame, g_this_const_str, &m_object_pointer_type);
Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame, g_this_const_str, &m_struct_vars->m_object_pointer_type);
if (!object_ptr_var)
{
@ -374,9 +393,9 @@ ClangExpressionDeclMap::GetObjectPointer
return false;
}
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(*exe_ctx,
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
object_ptr_var,
m_object_pointer_type.GetASTContext()));
NULL));
if (!location_value.get())
{
@ -387,10 +406,11 @@ ClangExpressionDeclMap::GetObjectPointer
if (location_value->GetValueType() == Value::eValueTypeLoadAddress)
{
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
uint32_t address_byte_size = exe_ctx->target->GetArchitecture().GetAddressByteSize();
lldb::ByteOrder address_byte_order = exe_ctx->process->GetByteOrder();
uint32_t address_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
lldb::ByteOrder address_byte_order = exe_ctx.process->GetByteOrder();
if (ClangASTType::GetClangTypeBitWidth(m_object_pointer_type.GetASTContext(), m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
if (ClangASTType::GetClangTypeBitWidth(m_struct_vars->m_object_pointer_type.GetASTContext(),
m_struct_vars->m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
{
err.SetErrorStringWithFormat("'this' is not of an expected pointer size");
return false;
@ -400,7 +420,7 @@ ClangExpressionDeclMap::GetObjectPointer
data.SetByteSize(address_byte_size);
Error read_error;
if (exe_ctx->process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
if (exe_ctx.process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
{
err.SetErrorStringWithFormat("Coldn't read 'this' from the target: %s", read_error.AsCString());
return false;
@ -424,57 +444,74 @@ ClangExpressionDeclMap::GetObjectPointer
bool
ClangExpressionDeclMap::Dematerialize
(
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
ClangExpressionVariable *&result,
Error &err
)
{
return DoMaterialize(true, exe_ctx, &result, err);
DidDematerialize();
}
void
ClangExpressionDeclMap::DidDematerialize()
{
if (m_material_vars.get())
{
if (m_material_vars->m_materialized_location)
{
//#define SINGLE_STEP_EXPRESSIONS
#ifndef SINGLE_STEP_EXPRESSIONS
m_material_vars->m_process->DeallocateMemory(m_material_vars->m_materialized_location);
#endif
m_material_vars->m_materialized_location = 0;
}
DisableMaterialVars();
}
}
bool
ClangExpressionDeclMap::DumpMaterializedStruct
(
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
Stream &s,
Error &err
)
{
if (!m_struct_laid_out)
assert (m_struct_vars.get());
assert (m_material_vars.get());
if (!m_struct_vars->m_struct_laid_out)
{
err.SetErrorString("Structure hasn't been laid out yet");
return false;
}
if (!exe_ctx)
{
err.SetErrorString("Received null execution context");
return false;
}
if (!exe_ctx->process)
if (!exe_ctx.process)
{
err.SetErrorString("Couldn't find the process");
return false;
}
if (!exe_ctx->target)
if (!exe_ctx.target)
{
err.SetErrorString("Couldn't find the target");
return false;
}
lldb::DataBufferSP data(new DataBufferHeap(m_struct_size, 0));
lldb::DataBufferSP data(new DataBufferHeap(m_struct_vars->m_struct_size, 0));
Error error;
if (exe_ctx->process->ReadMemory (m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
if (exe_ctx.process->ReadMemory (m_material_vars->m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
{
err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
return false;
}
DataExtractor extractor(data, exe_ctx->process->GetByteOrder(), exe_ctx->target->GetArchitecture().GetAddressByteSize());
DataExtractor extractor(data, exe_ctx.process->GetByteOrder(), exe_ctx.target->GetArchitecture().GetAddressByteSize());
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
member_index < num_members;
@ -487,15 +524,15 @@ ClangExpressionDeclMap::DumpMaterializedStruct
if (!member.m_jit_vars.get())
return false;
extractor.Dump(&s, // stream
member.m_jit_vars->m_offset, // offset
lldb::eFormatBytesWithASCII, // format
1, // byte size of individual entries
member.m_jit_vars->m_size, // number of entries
16, // entries per line
m_materialized_location + member.m_jit_vars->m_offset, // address to print
0, // bit size (bitfields only; 0 means ignore)
0); // bit alignment (bitfields only; 0 means ignore)
extractor.Dump(&s, // stream
member.m_jit_vars->m_offset, // offset
lldb::eFormatBytesWithASCII, // format
1, // byte size of individual entries
member.m_jit_vars->m_size, // number of entries
16, // entries per line
m_material_vars->m_materialized_location + member.m_jit_vars->m_offset, // address to print
0, // bit size (bitfields only; 0 means ignore)
0); // bit alignment (bitfields only; 0 means ignore)
s.PutChar('\n');
}
@ -507,68 +544,66 @@ bool
ClangExpressionDeclMap::DoMaterialize
(
bool dematerialize,
ExecutionContext *exe_ctx,
ExecutionContext &exe_ctx,
ClangExpressionVariable **result,
Error &err
)
{
assert (m_struct_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_struct_laid_out)
if (!m_struct_vars->m_struct_laid_out)
{
err.SetErrorString("Structure hasn't been laid out yet");
return LLDB_INVALID_ADDRESS;
}
if (!exe_ctx)
{
err.SetErrorString("Received null execution context");
return LLDB_INVALID_ADDRESS;
}
if (!exe_ctx->frame)
if (!exe_ctx.frame)
{
err.SetErrorString("Received null execution frame");
return LLDB_INVALID_ADDRESS;
}
if (!m_struct_size)
ClangPersistentVariables &persistent_vars = exe_ctx.process->GetPersistentVariables();
if (!m_struct_vars->m_struct_size)
{
if (log)
log->PutCString("Not bothering to allocate a struct because no arguments are needed");
m_allocated_area = NULL;
m_material_vars->m_allocated_area = NULL;
return true;
}
const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
const SymbolContext &sym_ctx(exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything));
if (!dematerialize)
{
if (m_materialized_location)
if (m_material_vars->m_materialized_location)
{
exe_ctx->process->DeallocateMemory(m_materialized_location);
m_materialized_location = 0;
exe_ctx.process->DeallocateMemory(m_material_vars->m_materialized_location);
m_material_vars->m_materialized_location = 0;
}
if (log)
log->PutCString("Allocating memory for materialized argument struct");
lldb::addr_t mem = exe_ctx->process->AllocateMemory(m_struct_alignment + m_struct_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
err);
lldb::addr_t mem = exe_ctx.process->AllocateMemory(m_struct_vars->m_struct_alignment + m_struct_vars->m_struct_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
err);
if (mem == LLDB_INVALID_ADDRESS)
return false;
m_allocated_area = mem;
m_material_vars->m_allocated_area = mem;
}
m_materialized_location = m_allocated_area;
m_material_vars->m_materialized_location = m_material_vars->m_allocated_area;
if (m_materialized_location % m_struct_alignment)
m_materialized_location += (m_struct_alignment - (m_materialized_location % m_struct_alignment));
if (m_material_vars->m_materialized_location % m_struct_vars->m_struct_alignment)
m_material_vars->m_materialized_location += (m_struct_vars->m_struct_alignment - (m_material_vars->m_materialized_location % m_struct_vars->m_struct_alignment));
for (uint64_t member_index = 0, num_members = m_struct_members.Size();
member_index < num_members;
@ -578,10 +613,14 @@ ClangExpressionDeclMap::DoMaterialize
ClangExpressionVariable *entity = NULL;
/*
if (member.m_parser_vars.get())
entity = m_found_entities.GetVariable(member.m_parser_vars->m_named_decl);
*/
ClangExpressionVariable *persistent_variable = m_persistent_vars->GetVariable(member.m_name);
entity = m_found_entities.GetVariable(member.m_name);
ClangExpressionVariable *persistent_variable = persistent_vars.GetVariable(member.m_name);
if (entity)
{
@ -589,12 +628,12 @@ ClangExpressionDeclMap::DoMaterialize
{
// This is a register variable
RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
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))
if (!DoMaterializeOneRegister(dematerialize, exe_ctx, *reg_ctx, *entity->m_register_info, m_material_vars->m_materialized_location + member.m_jit_vars->m_offset, err))
return false;
}
else
@ -602,13 +641,13 @@ ClangExpressionDeclMap::DoMaterialize
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))
if (!DoMaterializeOneVariable(dematerialize, exe_ctx, sym_ctx, member.m_name, member.m_user_type, m_material_vars->m_materialized_location + member.m_jit_vars->m_offset, err))
return false;
}
}
else if (persistent_variable)
{
if (member.m_name == m_result_name)
if (member.m_name == m_struct_vars->m_result_name)
{
if (!dematerialize)
continue;
@ -622,7 +661,7 @@ ClangExpressionDeclMap::DoMaterialize
if (log)
log->Printf("Searched for persistent variable %s and found %s", member.m_name.GetCString(), persistent_variable->m_name.GetCString());
if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, persistent_variable->m_name, m_materialized_location + member.m_jit_vars->m_offset, err))
if (!DoMaterializeOnePersistentVariable(dematerialize, exe_ctx, persistent_variable->m_name, m_material_vars->m_materialized_location + member.m_jit_vars->m_offset, err))
return false;
}
else
@ -644,8 +683,10 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
lldb::addr_t addr,
Error &err
)
{
ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
{
ClangPersistentVariables &persistent_vars = exe_ctx.process->GetPersistentVariables();
ClangExpressionVariable *pvar(persistent_vars.GetVariable(name));
if (!pvar)
{
@ -711,7 +752,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
var,
type.GetASTContext()));
NULL));
if (!location_value.get())
{
@ -1006,7 +1047,7 @@ ClangExpressionDeclMap::FindVariableInScope
const ConstString &name,
TypeFromUser *type
)
{
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
VariableList *var_list = frame.GetVariableList(true);
@ -1021,7 +1062,7 @@ ClangExpressionDeclMap::FindVariableInScope
if (!var_sp)
{
// Look for globals elsewhere in the module for the frame
ModuleSP module_sp (m_exe_ctx.frame->GetSymbolContext(eSymbolContextModule).module_sp);
ModuleSP module_sp (frame.GetSymbolContext(eSymbolContextModule).module_sp);
if (module_sp)
{
VariableList module_globals;
@ -1033,7 +1074,7 @@ ClangExpressionDeclMap::FindVariableInScope
if (!var_sp)
{
// Look for globals elsewhere in the program (all images)
TargetSP target_sp (m_exe_ctx.frame->GetSymbolContext(eSymbolContextTarget).target_sp);
TargetSP target_sp (frame.GetSymbolContext(eSymbolContextTarget).target_sp);
if (target_sp)
{
VariableList program_globals;
@ -1064,16 +1105,19 @@ ClangExpressionDeclMap::FindVariableInScope
void
ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name)
{
assert (m_struct_vars.get());
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("Hunting for a definition for '%s'", name.GetCString());
// Back out in all cases where we're not fully initialized
if (m_exe_ctx.frame == NULL)
if (m_parser_vars->m_exe_ctx->frame == NULL)
return;
if (m_ignore_lookups)
if (m_parser_vars->m_ignore_lookups)
{
if (log)
log->Printf("Ignoring a query during an import");
@ -1091,7 +1135,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
// doesn't start with our phony prefix of '$'
if (name_unique_cstr[0] != '$')
{
Variable *var = FindVariableInScope(*m_exe_ctx.frame, name);
Variable *var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name);
// If we found a variable in scope, no need to pull up function names
if (var != NULL)
@ -1100,7 +1144,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
}
else
{
m_sym_ctx.FindFunctionsByName (name, false, sc_list);
m_parser_vars->m_sym_ctx.FindFunctionsByName (name, false, sc_list);
bool found_specific = false;
Symbol *generic_symbol = NULL;
@ -1138,7 +1182,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
AddOneFunction(context, NULL, non_extern_symbol);
}
ClangNamespaceDecl namespace_decl (m_sym_ctx.FindNamespace(name));
ClangNamespaceDecl namespace_decl (m_parser_vars->m_sym_ctx.FindNamespace(name));
if (namespace_decl)
{
clang::NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl);
@ -1158,7 +1202,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
{
// Clang is looking for the type of "this"
VariableList *vars = m_exe_ctx.frame->GetVariableList(false);
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars)
return;
@ -1184,7 +1228,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
TypeFromUser this_user_type(this_type->GetClangType(),
this_type->GetClangAST());
m_object_pointer_type = this_user_type;
m_struct_vars->m_object_pointer_type = this_user_type;
void *pointer_target_type;
@ -1200,7 +1244,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
return;
}
ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
ClangExpressionVariable *pvar(m_parser_vars->m_persistent_vars->GetVariable(name));
if (pvar)
{
@ -1210,16 +1254,16 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
const char *reg_name(&name.GetCString()[1]);
if (m_exe_ctx.GetRegisterContext())
if (m_parser_vars->m_exe_ctx->GetRegisterContext())
{
const lldb::RegisterInfo *reg_info(m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name));
const lldb::RegisterInfo *reg_info(m_parser_vars->m_exe_ctx->GetRegisterContext()->GetRegisterInfoByName(reg_name));
if (reg_info)
AddOneRegister(context, reg_info);
}
}
lldb::TypeSP type_sp (m_sym_ctx.FindTypeByName (name));
lldb::TypeSP type_sp (m_parser_vars->m_sym_ctx.FindTypeByName (name));
if (type_sp)
{
@ -1347,7 +1391,7 @@ ClangExpressionDeclMap::GetVariableValue
Address so_addr(var_location->GetScalar().ULongLong(), object_file->GetSectionList());
lldb::addr_t load_addr = so_addr.GetLoadAddress(m_exe_ctx.target);
lldb::addr_t load_addr = so_addr.GetLoadAddress(exe_ctx.target);
var_location->GetScalar() = load_addr;
var_location->SetValueType(Value::eValueTypeLoadAddress);
@ -1363,12 +1407,14 @@ void
ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
Variable* var)
{
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
TypeFromUser ut;
TypeFromParser pt;
Value *var_location = GetVariableValue (m_exe_ctx,
Value *var_location = GetVariableValue (*m_parser_vars->m_exe_ctx,
var,
context.GetASTContext(),
&ut,
@ -1494,6 +1540,8 @@ ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
Function* fun,
Symbol* symbol)
{
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
NamedDecl *fun_decl;
@ -1545,7 +1593,7 @@ ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
return;
}
lldb::addr_t load_addr = fun_address->GetLoadAddress(m_exe_ctx.target);
lldb::addr_t load_addr = fun_address->GetLoadAddress(m_parser_vars->m_exe_ctx->target);
fun_location->SetValueType(Value::eValueTypeLoadAddress);
fun_location->GetScalar() = load_addr;
@ -1619,13 +1667,15 @@ ClangExpressionDeclMap::GuardedCopyType (ASTContext *dest_context,
ASTContext *source_context,
void *clang_type)
{
m_ignore_lookups = true;
assert (m_parser_vars.get());
m_parser_vars->m_ignore_lookups = true;
void *ret = ClangASTContext::CopyType (dest_context,
source_context,
clang_type);
m_ignore_lookups = false;
m_parser_vars->m_ignore_lookups = false;
return ret;
}

View File

@ -225,7 +225,9 @@ ClangUserExpression::Parse (Stream &error_stream,
m_desired_type = desired_type;
m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
m_expr_decl_map.reset(new ClangExpressionDeclMap());
m_expr_decl_map->WillParse(exe_ctx);
ClangExpressionParser parser(target_triple.GetCString(), *this);
@ -234,6 +236,9 @@ ClangUserExpression::Parse (Stream &error_stream,
if (num_errors)
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
m_expr_decl_map->DidParse();
return false;
}
@ -254,6 +259,8 @@ ClangUserExpression::Parse (Stream &error_stream,
if (log)
log->Printf("Code can be interpreted.");
m_expr_decl_map->DidParse();
return true;
}
@ -267,6 +274,8 @@ ClangUserExpression::Parse (Stream &error_stream,
Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);
m_expr_decl_map->DidParse();
if (jit_error.Success())
{
return true;
@ -292,13 +301,13 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
Error materialize_error;
if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, exe_ctx, materialize_error)))
{
error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
return false;
}
if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
{
error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
return false;
@ -319,7 +328,7 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
if (struct_address)
{
if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
if (!m_expr_decl_map->DumpMaterializedStruct(exe_ctx, args, dump_error))
{
log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
}
@ -362,7 +371,7 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
{
Error expr_error;
if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
if (!m_expr_decl_map->Dematerialize(exe_ctx, result, expr_error))
{
error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
return false;

View File

@ -99,7 +99,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
// Parse the expression
//
m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
m_expr_decl_map.reset(new ClangExpressionDeclMap());
m_expr_decl_map->WillParse(exe_ctx);
ClangExpressionParser parser(target_triple.GetCString(), *this);
@ -120,6 +122,8 @@ ClangUtilityFunction::Install (Stream &error_stream,
Error jit_error = parser.MakeJIT (m_jit_begin, m_jit_end, exe_ctx);
m_expr_decl_map->DidParse();
m_expr_decl_map.reset();
if (jit_error.Success())