Implemented a major overhaul of the way variables are handled

by LLDB.  Instead of being materialized into the input structure
passed to the expression, variables are left in place and pointers
to them are materialzied into the structure.  Variables not resident
in memory (notably, registers) get temporary memory regions allocated
for them.

Persistent variables are the most complex part of this, because they
are made in various ways and there are different expectations about
their lifetime.  Persistent variables now have flags indicating their
status and what the expectations for longevity are.  They can be
marked as residing in target memory permanently -- this is the
default for result variables from expressions entered on the command
line and for explicitly declared persistent variables (but more on
that below).  Other result variables have their memory freed.

Some major improvements resulting from this include being able to
properly take the address of variables, better and cleaner support
for functions that return references, and cleaner C++ support in
general.  One problem that remains is the problem of explicitly
declared persistent variables; I have not yet implemented the code
that makes references to them into indirect references, so currently
materialization and dematerialization of these variables is broken.

llvm-svn: 123371
This commit is contained in:
Sean Callanan 2011-01-13 08:53:35 +00:00
parent 02cde7ffa4
commit 92adcac9ec
20 changed files with 669 additions and 151 deletions

View File

@ -70,9 +70,14 @@ public:
//------------------------------------------------------------------
/// Constructor
///
/// Initializes class variabes.
/// Initializes class variables.
///
/// @param[in] keep_result_in_memory
/// If true, inhibits the normal deallocation of the memory for
/// the result persistent variable, and instead marks the variable
/// as persisting.
//------------------------------------------------------------------
ClangExpressionDeclMap ();
ClangExpressionDeclMap (bool keep_result_in_memory);
//------------------------------------------------------------------
/// Destructor
@ -151,7 +156,9 @@ public:
bool
AddPersistentVariable (const clang::NamedDecl *decl,
const ConstString &name,
TypeFromParser type);
TypeFromParser type,
bool is_result,
bool is_lvalue);
//------------------------------------------------------------------
/// [Used by IRForTarget] Add a variable to the struct that needs to
@ -443,6 +450,7 @@ public:
private:
ClangExpressionVariableList 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.
bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory.
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
@ -797,11 +805,11 @@ private:
/// @param[in] sym_ctx
/// The symbol context to use (for looking the variable up).
///
/// @param[in] name
/// The name of the variable (for looking the variable up).
///
/// @param[in] type
/// The required type of the variable (for looking the variable up).
/// @param[in] expr_var
/// The entity that the expression parser uses for the variable.
/// In case the variable needs to be copied into the target's
/// memory, this location is stored in the variable during
/// materialization and cleared when it is demateralized.
///
/// @param[in] addr
/// The address at which to materialize the variable.
@ -817,8 +825,7 @@ private:
DoMaterializeOneVariable (bool dematerialize,
ExecutionContext &exe_ctx,
const SymbolContext &sym_ctx,
const ConstString &name,
TypeFromUser type,
lldb::ClangExpressionVariableSP &expr_var,
lldb::addr_t addr,
Error &err);

View File

@ -199,7 +199,6 @@ public:
void
ValueUpdated ();
typedef lldb::SharedPtr<ValueObjectConstResult>::Type ValueObjectConstResultSP;
//----------------------------------------------------------------------
@ -207,9 +206,22 @@ public:
//----------------------------------------------------------------------
std::auto_ptr<ParserVars> m_parser_vars;
std::auto_ptr<JITVars> m_jit_vars;
//ValueObjectConstResultSP m_valojb_sp;
lldb::ValueObjectSP m_valojb_sp;
enum Flags
{
EVNone = 0,
EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program
EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process
EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization
EVKeepInTarget = 1 << 5 ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
};
uint16_t m_flags; // takes elements of Flags
lldb::ValueObjectSP m_frozen_sp;
lldb::ValueObjectSP m_live_sp;
private:
DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
};

View File

@ -81,6 +81,10 @@ public:
/// The type that the expression should be coerced to. If NULL,
/// inferred from the expression itself.
///
/// @param[in] keep_result_in_memory
/// True if the resulting persistent variable should reside in
/// target memory, if applicable.
///
/// @param[out] const_result
/// If this is non-NULL, the expression has no side effects, and
/// the expression returns a constant result, then that result
@ -93,6 +97,7 @@ public:
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
bool keep_result_in_memory,
lldb::ClangExpressionVariableSP *const_result = NULL);
//------------------------------------------------------------------
@ -109,6 +114,7 @@ public:
/// If true, and the execution stops before completion, we unwind the
/// function call, and return the program state to what it was before the
/// execution. If false, we leave the program in the stopped state.
///
/// @param[in] shared_ptr_to_me
/// This is a shared pointer to this ClangUserExpression. This is
/// needed because Execute can push a thread plan that will hold onto
@ -127,12 +133,14 @@ public:
Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
bool discard_on_error,
bool keep_in_memory,
ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
ThreadPlan *
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx);
bool
FinalizeJITExecution (Stream &error_stream,
ExecutionContext &exe_ctx,
@ -232,6 +240,14 @@ public:
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
///
/// @param[in] discard_on_error
/// True if the thread's state should be restored in the case
/// of an error.
///
/// @param[in] keep_in_memory
/// True if the resulting persistent variable should reside in
/// target memory, if applicable.
///
/// @param[in] expr_cstr
/// A C string containing the expression to be evaluated.
///
@ -248,6 +264,7 @@ public:
static lldb::ExecutionResults
Evaluate (ExecutionContext &exe_ctx,
bool discard_on_error,
bool keep_in_memory,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);

View File

@ -448,12 +448,14 @@ private:
/// Flags
bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
std::string m_func_name; ///< The name of the function to translate
lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...)
lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type
lldb::ClangExpressionVariableSP *m_const_result; ///< If non-NULL, this value should be set to the return value of the expression if it is constant and the expression has no side effects
bool m_has_side_effects; ///< True if the function's result cannot be simply determined statically
bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult)
private:
//------------------------------------------------------------------

View File

@ -529,11 +529,25 @@ public:
CreatePointerType (clang::ASTContext *ast,
lldb::clang_type_t clang_type);
static lldb::clang_type_t
CreateLValueReferenceType (clang::ASTContext *ast_context,
lldb::clang_type_t clang_type);
static lldb::clang_type_t
CreateRValueReferenceType (clang::ASTContext *ast_context,
lldb::clang_type_t clang_type);
lldb::clang_type_t
CreateLValueReferenceType (lldb::clang_type_t clang_type);
CreateLValueReferenceType (lldb::clang_type_t clang_type)
{
return ClangASTContext::CreateLValueReferenceType(getASTContext(), clang_type);
}
lldb::clang_type_t
CreateRValueReferenceType (lldb::clang_type_t clang_type);
CreateRValueReferenceType (lldb::clang_type_t clang_type)
{
return ClangASTContext::CreateRValueReferenceType(getASTContext(), clang_type);
}
lldb::clang_type_t
CreateMemberPointerType (lldb::clang_type_t clang_pointee_type,

View File

@ -476,6 +476,7 @@ public:
EvaluateExpression (const char *expression,
StackFrame *frame,
bool unwind_on_error,
bool keep_in_memory,
lldb::ValueObjectSP &result_valobj_sp);
ClangPersistentVariables &

View File

@ -689,8 +689,9 @@ SBFrame::EvaluateExpression (const char *expr)
{
ExecutionResults exe_results;
const bool unwind_on_error = true;
const bool keep_in_memory = false;
exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, *expr_result);
exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, keep_in_memory, *expr_result);
}
if (expr_log)

View File

@ -199,7 +199,7 @@ BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type))
if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, false /* keep_in_memory */))
{
// Errors mean we should stop.
return NULL;

View File

@ -237,7 +237,10 @@ CommandObjectExpression::EvaluateExpression
lldb::ValueObjectSP result_valobj_sp;
lldb::ExecutionResults exe_results;
exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, result_valobj_sp);
bool keep_in_memory = true;
exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, result_valobj_sp);
if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
{

View File

@ -1316,7 +1316,7 @@ ValueObject::AddressOf (Error &error)
ClangASTContext::CreatePointerType (ast, clang_type),
ConstString (name.c_str()),
addr,
address_type,
eAddressTypeInvalid,
m_data.GetAddressByteSize()));
}
}

View File

@ -246,6 +246,49 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
// No auxiliary variable necessary; expression returns void
return true;
// is_lvalue is used to record whether the expression returns an assignable Lvalue or an
// Rvalue. This is relevant because they are handled differently.
//
// For Lvalues
//
// - In AST result synthesis (here!) the expression E is transformed into an initialization
// T *$__lldb_expr_result_ptr = &E.
//
// - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
// passed into the expression.
//
// - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
// an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent
// variables are treated similarly, having been materialized as references, but in those
// cases the value of the reference itself is never modified.)
//
// - During materialization, $0 (the result persistent variable) is ignored.
//
// - During dematerialization, $0 is marked up as a load address with value equal to the
// contents of the structure entry.
//
// For Rvalues
//
// - In AST result synthesis the expression E is transformed into an initialization
// static T $__lldb_expr_result = E.
//
// - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
// passed into the expression.
//
// - In IR transformations, an instruction is inserted at the beginning of the function to
// dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result
// are redirected at that dereferenced version. Guard variables for the static variable
// are excised.
//
// - During materialization, $0 (the result persistent variable) is populated with the location
// of a newly-allocated area of memory.
//
// - During dematerialization, $0 is ignored.
bool is_lvalue =
(last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
(last_expr->getObjectKind() == OK_Ordinary);
QualType expr_qual_type = last_expr->getType();
clang::Type *expr_type = expr_qual_type.getTypePtr();
@ -259,22 +302,51 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
{
std::string s = expr_qual_type.getAsString();
log->Printf("Last statement's type: %s", s.c_str());
log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
}
IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
clang::VarDecl *result_decl = VarDecl::Create(Ctx,
DC,
SourceLocation(),
&result_id,
expr_qual_type,
NULL,
SC_Static,
SC_Static);
clang::VarDecl *result_decl;
if (!result_decl)
return false;
if (is_lvalue)
{
IdentifierInfo &result_ptr_id = Ctx.Idents.get("$__lldb_expr_result_ptr");
QualType ptr_qual_type = Ctx.getPointerType(expr_qual_type);
result_decl = VarDecl::Create(Ctx,
DC,
SourceLocation(),
&result_ptr_id,
ptr_qual_type,
NULL,
SC_Static,
SC_Static);
if (!result_decl)
return false;
ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
m_sema->AddInitializerToDecl(result_decl, address_of_expr.take());
}
else
{
IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
result_decl = VarDecl::Create(Ctx,
DC,
SourceLocation(),
&result_id,
expr_qual_type,
NULL,
SC_Static,
SC_Static);
if (!result_decl)
return false;
m_sema->AddInitializerToDecl(result_decl, last_expr);
}
DC->addDecl(result_decl);
@ -282,7 +354,7 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
// call AddInitializerToDecl
//
m_sema->AddInitializerToDecl(result_decl, last_expr);
//m_sema->AddInitializerToDecl(result_decl, last_expr);
/////////////////////////////////
// call ConvertDeclToDeclGroup

View File

@ -45,11 +45,12 @@ using namespace lldb;
using namespace lldb_private;
using namespace clang;
ClangExpressionDeclMap::ClangExpressionDeclMap () :
ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory) :
m_found_entities (),
m_struct_members (),
m_parser_vars (),
m_struct_vars ()
m_struct_vars (),
m_keep_result_in_memory (keep_result_in_memory)
{
EnableStructVars();
}
@ -187,6 +188,8 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
return lldb::ClangExpressionVariableSP();
}
}
pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
return pvar_sp;
}
@ -196,11 +199,15 @@ ClangExpressionDeclMap::AddPersistentVariable
(
const clang::NamedDecl *decl,
const ConstString &name,
TypeFromParser parser_type
TypeFromParser parser_type,
bool is_result,
bool is_lvalue
)
{
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
TypeFromUser user_type(ClangASTContext::CopyType(context,
@ -219,6 +226,24 @@ ClangExpressionDeclMap::AddPersistentVariable
if (!var_sp)
return false;
if (is_result)
var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
else
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
if (is_lvalue)
{
var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
}
else
{
var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
}
if (log)
log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
var_sp->EnableParserVars();
var_sp->m_parser_vars->m_named_decl = decl;
@ -441,7 +466,7 @@ ClangExpressionDeclMap::Materialize
m_material_vars->m_process = exe_ctx.process;
bool result = DoMaterialize(false, exe_ctx, NULL, err);
bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err);
if (result)
struct_address = m_material_vars->m_materialized_location;
@ -740,9 +765,8 @@ ClangExpressionDeclMap::DoMaterialize
if (!DoMaterializeOneVariable (dematerialize,
exe_ctx,
sym_ctx,
member_sp->GetName(),
member_sp->GetTypeFromUser(),
sym_ctx,
member_sp,
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
err))
return false;
@ -754,20 +778,21 @@ ClangExpressionDeclMap::DoMaterialize
// with with a '$' character...
if (member_sp->GetName().AsCString ("!")[0] == '$' && persistent_vars.ContainsVariable(member_sp))
{
bool keep_this_in_memory = false;
if (member_sp->GetName() == m_struct_vars->m_result_name)
{
if (!dematerialize)
continue;
if (log)
log->PutCString("Found result member in the struct");
if (result_sp_ptr)
*result_sp_ptr = member_sp;
keep_this_in_memory = m_keep_result_in_memory;
}
if (!DoMaterializeOnePersistentVariable (dematerialize,
exe_ctx,
exe_ctx,
member_sp,
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
err))
@ -784,6 +809,63 @@ ClangExpressionDeclMap::DoMaterialize
return true;
}
static bool WriteAddressInto
(
ExecutionContext &exe_ctx,
lldb::addr_t target,
lldb::addr_t address,
Error &err
)
{
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
StreamString str (0 | Stream::eBinary,
pointer_byte_size,
exe_ctx.process->GetByteOrder());
switch (pointer_byte_size)
{
default:
assert(!"Unhandled byte size");
case 4:
{
uint32_t address32 = address & 0xffffffffll;
str.PutRawBytes(&address32, sizeof(address32), eByteOrderHost, eByteOrderInvalid);
}
break;
case 8:
{
uint64_t address64 = address;
str.PutRawBytes(&address64, sizeof(address64), eByteOrderHost, eByteOrderInvalid);
}
break;
}
return (exe_ctx.process->WriteMemory (target, str.GetData(), pointer_byte_size, err) == pointer_byte_size);
}
static lldb::addr_t ReadAddressFrom
(
ExecutionContext &exe_ctx,
lldb::addr_t source,
Error &err
)
{
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
DataBufferHeap *buf = new DataBufferHeap(pointer_byte_size, 0);
DataBufferSP buf_sp(buf);
if (exe_ctx.process->ReadMemory (source, buf->GetBytes(), pointer_byte_size, err) != pointer_byte_size)
return LLDB_INVALID_ADDRESS;
DataExtractor extractor (buf_sp, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
uint32_t offset = 0;
return (lldb::addr_t)extractor.GetPointer(&offset);
}
bool
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
(
@ -794,6 +876,8 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
Error &err
)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!var_sp)
{
err.SetErrorString("Invalid persistent variable");
@ -808,20 +892,167 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
Error error;
lldb::addr_t mem; // The address of a spare memory area used to hold the persistent variable.
if (dematerialize)
{
var_sp->ValueUpdated ();
if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
if (log)
log->Printf("Dematerializing persistent variable with flags 0x%hx", var_sp->m_flags);
if ((var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
{
err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
// Get the location of the target out of the struct.
Error read_error;
mem = ReadAddressFrom(exe_ctx, addr, read_error);
if (mem == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't read address of %s from struct: %s", var_sp->GetName().GetCString(), error.AsCString());
return false;
}
if (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
!var_sp->m_live_sp)
{
// If the reference comes from the program, then the ClangExpressionVariable's
// live variable data hasn't been set up yet. Do this now.
var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
var_sp->GetTypeFromUser().GetOpaqueQualType(),
var_sp->GetName(),
mem,
lldb::eAddressTypeLoad,
pvar_byte_size));
}
if (!var_sp->m_live_sp)
{
err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", var_sp->GetName().GetCString());
return false;
}
if (var_sp->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
{
err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", var_sp->GetName().GetCString());
return false;
}
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
{
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
if (log)
log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
// Read the contents of the spare memory area
if (log)
log->Printf("Read");
var_sp->ValueUpdated ();
if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
return false;
}
var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
}
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
!(var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
{
if (m_keep_result_in_memory)
{
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
}
else
{
Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
if (!err.Success())
{
err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", var_sp->GetName().GetCString(), deallocate_error.AsCString());
return false;
}
}
}
}
else
{
err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
return false;
}
}
else
{
if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
if (log)
log->Printf("Materializing persistent variable with flags 0x%hx", var_sp->m_flags);
if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
{
err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
// Allocate a spare memory area to store the persistent variable's contents.
Error allocate_error;
mem = exe_ctx.process->AllocateMemory(pvar_byte_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
allocate_error);
if (mem == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", var_sp->GetName().GetCString(), allocate_error.AsCString());
return false;
}
if (log)
log->Printf("Allocated %s (0x%llx) sucessfully", var_sp->GetName().GetCString(), mem);
// Put the location of the spare memory into the live data of the ValueObject.
var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
var_sp->GetTypeFromUser().GetOpaqueQualType(),
var_sp->GetName(),
mem,
lldb::eAddressTypeLoad,
pvar_byte_size));
// Clear the flag if the variable will never be deallocated.
if (var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
// Write the contents of the variable to the area.
if (exe_ctx.process->WriteMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
return false;
}
}
if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
{
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
// Now write the location of the area into the struct.
Error write_error;
if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
return false;
}
if (log)
log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
}
else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)
{
err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
return false;
}
}
@ -835,8 +1066,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
bool dematerialize,
ExecutionContext &exe_ctx,
const SymbolContext &sym_ctx,
const ConstString &name,
TypeFromUser type,
ClangExpressionVariableSP &expr_var,
lldb::addr_t addr,
Error &err
)
@ -846,6 +1076,11 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
if (!exe_ctx.frame || !exe_ctx.process)
return false;
// Vital information about the value
const ConstString &name(expr_var->GetName());
TypeFromUser type(expr_var->GetTypeFromUser());
Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type);
if (!var)
@ -869,8 +1104,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
// The size of the type contained in addr
size_t addr_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
size_t addr_byte_size = addr_bit_size % 8 ? ((addr_bit_size + 8) / 8) : (addr_bit_size / 8);
size_t value_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
size_t value_byte_size = value_bit_size % 8 ? ((value_bit_size + 8) / 8) : (value_bit_size / 8);
Value::ValueType value_type = location_value->GetValueType();
@ -888,40 +1123,21 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
break;
case Value::eValueTypeLoadAddress:
{
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
DataBufferHeap data;
data.SetByteSize(addr_byte_size);
lldb::addr_t src_addr;
lldb::addr_t dest_addr;
if (dematerialize)
if (!dematerialize)
{
src_addr = addr;
dest_addr = value_addr;
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
Error error;
if (!WriteAddressInto(exe_ctx,
addr,
value_addr,
error))
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
return false;
}
}
else
{
src_addr = value_addr;
dest_addr = addr;
}
Error error;
if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
return false;
}
if (exe_ctx.process->WriteMemory (dest_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
return false;
}
if (log)
log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr);
}
break;
case Value::eValueTypeScalar:
@ -929,13 +1145,14 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
if (location_value->GetContextType() != Value::eContextTypeRegisterInfo)
{
StreamString ss;
location_value->Dump(&ss);
err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
return false;
}
lldb::addr_t mem; // The address of a spare memory area aused to hold the variable.
lldb::RegisterInfo *register_info = location_value->GetRegisterInfo();
if (!register_info)
@ -957,6 +1174,22 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
if (dematerialize)
{
// Get the location of the spare memory area out of the variable's live data.
if (!expr_var->m_live_sp)
{
err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", name.GetCString());
return false;
}
if (expr_var->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
{
err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", name.GetCString());
return false;
}
mem = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
// Moving from addr into a register
//
// Case 1: addr_byte_size and register_byte_size are the same
@ -974,7 +1207,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
// |AABB0000| Register contents [on little-endian hardware]
// |0000AABB| Register contents [on big-endian hardware]
if (addr_byte_size > register_byte_size)
if (value_byte_size > register_byte_size)
{
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
return false;
@ -991,14 +1224,14 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
register_offset = 0;
break;
case lldb::eByteOrderBig:
register_offset = register_byte_size - addr_byte_size;
register_offset = register_byte_size - value_byte_size;
break;
}
DataBufferHeap register_data (register_byte_size, 0);
Error error;
if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes() + register_offset, addr_byte_size, error) != addr_byte_size)
if (exe_ctx.process->ReadMemory (mem, register_data.GetBytes() + register_offset, value_byte_size, error) != value_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
return false;
@ -1011,9 +1244,54 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
return false;
}
// Deallocate the spare area and clear the variable's live data.
Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
if (!deallocate_error.Success())
{
err.SetErrorStringWithFormat("Couldn't deallocate spare memory area for %s: %s", name.GetCString(), deallocate_error.AsCString());
return false;
}
expr_var->m_live_sp.reset();
}
else
{
// Allocate a spare memory area to place the register's contents into. This memory area will be pointed to by the slot in the
// struct.
Error allocate_error;
mem = exe_ctx.process->AllocateMemory(value_byte_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
allocate_error);
if (mem == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
return false;
}
// Put the location of the spare memory into the live data of the ValueObject.
expr_var->m_live_sp.reset(new lldb_private::ValueObjectConstResult(type.GetASTContext(),
type.GetOpaqueQualType(),
name,
mem,
lldb::eAddressTypeLoad,
value_byte_size));
// Now write the location of the area into the struct.
Error write_error;
if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
return false;
}
// Moving from a register into addr
//
// Case 1: addr_byte_size and register_byte_size are the same
@ -1031,7 +1309,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
// |AABB| Address contents on little-endian hardware
// |CCDD| Address contents on big-endian hardware
if (addr_byte_size > register_byte_size)
if (value_byte_size > register_byte_size)
{
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
return false;
@ -1048,7 +1326,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
register_offset = 0;
break;
case lldb::eByteOrderBig:
register_offset = register_byte_size - addr_byte_size;
register_offset = register_byte_size - value_byte_size;
break;
}
@ -1060,7 +1338,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
return false;
}
const void *register_data = register_extractor.GetData(&register_offset, addr_byte_size);
const void *register_data = register_extractor.GetData(&register_offset, value_byte_size);
if (!register_data)
{
@ -1068,10 +1346,9 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
return false;
}
Error error;
if (exe_ctx.process->WriteMemory (addr, register_data, addr_byte_size, error) != addr_byte_size)
if (exe_ctx.process->WriteMemory (mem, register_data, value_byte_size, write_error) != value_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
return false;
}
}
@ -1581,7 +1858,7 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
if (!var_location)
return;
NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType()));
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (entity_name,
@ -1619,7 +1896,7 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
user_type.GetOpaqueQualType()),
context.GetASTContext());
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(parser_type.GetASTContext(), parser_type.GetOpaqueQualType()));
pvar_sp->EnableParserVars();
pvar_sp->m_parser_vars->m_parser_type = parser_type;

View File

@ -28,14 +28,16 @@ using namespace clang;
ClangExpressionVariable::ClangExpressionVariable(lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
m_parser_vars(),
m_jit_vars (),
m_valojb_sp (new ValueObjectConstResult(byte_order, addr_byte_size))
m_frozen_sp (new ValueObjectConstResult(byte_order, addr_byte_size)),
m_flags (EVNone)
{
}
ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
m_parser_vars(),
m_jit_vars (),
m_valojb_sp (valobj_sp)
m_frozen_sp (valobj_sp),
m_flags (EVNone)
{
}
@ -45,76 +47,76 @@ ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &val
size_t
ClangExpressionVariable::GetByteSize ()
{
return m_valojb_sp->GetByteSize();
return m_frozen_sp->GetByteSize();
}
const ConstString &
ClangExpressionVariable::GetName ()
{
return m_valojb_sp->GetName();
return m_frozen_sp->GetName();
}
lldb::ValueObjectSP
ClangExpressionVariable::GetValueObject()
{
return m_valojb_sp;
return m_frozen_sp;
}
lldb::RegisterInfo *
ClangExpressionVariable::GetRegisterInfo()
{
return m_valojb_sp->GetValue().GetRegisterInfo();
return m_frozen_sp->GetValue().GetRegisterInfo();
}
void
ClangExpressionVariable::SetRegisterInfo (const lldb::RegisterInfo *reg_info)
{
return m_valojb_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<lldb::RegisterInfo *>(reg_info));
return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<lldb::RegisterInfo *>(reg_info));
}
lldb::clang_type_t
ClangExpressionVariable::GetClangType()
{
return m_valojb_sp->GetClangType();
return m_frozen_sp->GetClangType();
}
void
ClangExpressionVariable::SetClangType(lldb::clang_type_t clang_type)
{
m_valojb_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
m_frozen_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
}
clang::ASTContext *
ClangExpressionVariable::GetClangAST()
{
return m_valojb_sp->GetClangAST();
return m_frozen_sp->GetClangAST();
}
void
ClangExpressionVariable::SetClangAST (clang::ASTContext *ast)
{
m_valojb_sp->SetClangAST (ast);
m_frozen_sp->SetClangAST (ast);
}
TypeFromUser
ClangExpressionVariable::GetTypeFromUser()
{
TypeFromUser tfu (m_valojb_sp->GetClangType(), m_valojb_sp->GetClangAST());
TypeFromUser tfu (m_frozen_sp->GetClangType(), m_frozen_sp->GetClangAST());
return tfu;
}
uint8_t *
ClangExpressionVariable::GetValueBytes()
{
const size_t byte_size = m_valojb_sp->GetByteSize();
const size_t byte_size = m_frozen_sp->GetByteSize();
if (byte_size > 0)
{
if (m_valojb_sp->GetDataExtractor().GetByteSize() < byte_size)
if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
{
m_valojb_sp->GetValue().ResizeData(byte_size);
m_valojb_sp->GetValue().GetData (m_valojb_sp->GetDataExtractor());
m_frozen_sp->GetValue().ResizeData(byte_size);
m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
}
return const_cast<uint8_t *>(m_valojb_sp->GetDataExtractor().GetDataStart());
return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
}
return NULL;
}
@ -122,12 +124,12 @@ ClangExpressionVariable::GetValueBytes()
void
ClangExpressionVariable::SetName (const ConstString &name)
{
m_valojb_sp->SetName (name);
m_frozen_sp->SetName (name);
}
void
ClangExpressionVariable::ValueUpdated ()
{
m_valojb_sp->ValueUpdated ();
m_frozen_sp->ValueUpdated ();
}

View File

@ -144,6 +144,7 @@ bool
ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
bool keep_result_in_memory,
lldb::ClangExpressionVariableSP *const_result)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -248,7 +249,7 @@ ClangUserExpression::Parse (Stream &error_stream,
m_desired_type = desired_type;
m_expr_decl_map.reset(new ClangExpressionDeclMap());
m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
m_expr_decl_map->WillParse(exe_ctx);
@ -398,7 +399,7 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
ThreadPlan *
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx)
ExecutionContext &exe_ctx)
{
lldb::addr_t struct_address;
@ -460,6 +461,7 @@ lldb::ExecutionResults
ClangUserExpression::Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
bool discard_on_error,
bool keep_in_memory,
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result)
{
@ -556,6 +558,7 @@ ClangUserExpression::DwarfOpcodeStream ()
lldb::ExecutionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
bool discard_on_error,
bool keep_in_memory,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp)
@ -619,7 +622,7 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
{
lldb::ClangExpressionVariableSP expr_result;
if (const_result.get())
if (const_result.get() && !keep_in_memory)
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
@ -635,7 +638,8 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
execution_results = user_expression_sp->Execute (error_stream,
exe_ctx,
discard_on_error,
discard_on_error,
keep_in_memory,
user_expression_sp,
expr_result);

View File

@ -99,7 +99,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
// Parse the expression
//
m_expr_decl_map.reset(new ClangExpressionDeclMap());
bool keep_result_in_memory = false;
m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
m_expr_decl_map->WillParse(exe_ctx);

View File

@ -43,7 +43,8 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
m_func_name(func_name),
m_resolve_vars(resolve_vars),
m_const_result(const_result),
m_has_side_effects(NULL)
m_has_side_effects(false),
m_result_is_pointer(false)
{
}
@ -153,10 +154,19 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
vi != ve;
++vi)
{
if (strstr(vi->first(), "$__lldb_expr_result_ptr") &&
!strstr(vi->first(), "GV"))
{
result_name = vi->first();
m_result_is_pointer = true;
break;
}
if (strstr(vi->first(), "$__lldb_expr_result") &&
!strstr(vi->first(), "GV"))
{
result_name = vi->first();
m_result_is_pointer = false;
break;
}
}
@ -178,7 +188,7 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
{
if (log)
log->PutCString("Result variable had no data");
return false;
}
@ -240,14 +250,43 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
// Get the next available result name from m_decl_map and create the persistent
// variable for it
lldb_private::TypeFromParser result_decl_type (result_decl->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
lldb_private::ConstString new_result_name (m_decl_map->GetPersistentResultName());
m_decl_map->AddPersistentVariable(result_decl, new_result_name, result_decl_type);
lldb_private::TypeFromParser result_decl_type;
if (m_result_is_pointer)
{
clang::QualType pointer_qual_type = result_decl->getType();
clang::Type *pointer_type = pointer_qual_type.getTypePtr();
clang::PointerType *pointer_pointertype = dyn_cast<clang::PointerType>(pointer_type);
if (!pointer_pointertype)
{
if (log)
log->PutCString("Expected result to have pointer type, but it did not");
return false;
}
clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
result_decl_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext());
}
else
{
result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
}
m_result_name = m_decl_map->GetPersistentResultName();
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
m_decl_map->AddPersistentVariable(result_decl,
m_result_name,
result_decl_type,
true,
m_result_is_pointer);
if (log)
log->Printf("Creating a new result global: \"%s\"", new_result_name.GetCString());
log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
// Construct a new result global and set up its metadata
@ -256,7 +295,7 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
false, /* not constant */
GlobalValue::ExternalLinkage,
NULL, /* no initializer */
new_result_name.GetCString ());
m_result_name.GetCString ());
// It's too late in compilation to create a new VarDecl for this, but we don't
// need to. We point the metadata at the old VarDecl. This creates an odd
@ -307,7 +346,7 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
if (!m_has_side_effects)
{
MaybeSetConstantResult (initializer,
new_result_name,
m_result_name,
result_decl_type);
}
@ -800,7 +839,7 @@ IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc,
StringRef decl_name (decl->getName());
lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type))
if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
return false;
GlobalVariable *persistent_global = new GlobalVariable(llvm_module,
@ -964,9 +1003,27 @@ IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
return false;
}
clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_type));
clang::QualType qual_type;
const Type *value_type;
if (!name.compare("$__lldb_expr_result"))
{
// The $__lldb_expr_result name indicates the the return value has allocated as
// a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
// accesses to this static variable need to be redirected to the result of dereferencing
// a pointer that is passed in as one of the arguments.
//
// Consequently, when reporting the size of the type, we report a pointer type pointing
// to the type of $__lldb_expr_result, not the type itself.
const Type *value_type = global_variable->getType();
qual_type = ast_context->getPointerType(clang::QualType::getFromOpaquePtr(opaque_type));
value_type = PointerType::get(global_variable->getType(), 0);
}
else
{
qual_type = clang::QualType::getFromOpaquePtr(opaque_type);
value_type = global_variable->getType();
}
size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
@ -1479,12 +1536,31 @@ IRForTarget::ReplaceVariables (Module &llvm_module, Function &llvm_function)
ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset));
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction);
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
Value *replacement;
if (Constant *constant = dyn_cast<Constant>(value))
UnfoldConstant(constant, bit_cast, FirstEntryInstruction);
// Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
// variable is an rvalue, we have to synthesize a dereference of the appropriate structure
// entry in order to produce the static variable that the AST thinks it is accessing.
if (name == m_result_name && !m_result_is_pointer)
{
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType()->getPointerTo(), "", FirstEntryInstruction);
LoadInst *load = new LoadInst(bit_cast, "", FirstEntryInstruction);
replacement = load;
}
else
value->replaceAllUsesWith(bit_cast);
{
BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
replacement = bit_cast;
}
if (Constant *constant = dyn_cast<Constant>(value))
UnfoldConstant(constant, replacement, FirstEntryInstruction);
else
value->replaceAllUsesWith(replacement);
if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
var->eraseFromParent();
@ -1507,7 +1583,7 @@ IRForTarget::runOnModule (Module &llvm_module)
{
if (log)
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
return false;
}

View File

@ -859,7 +859,7 @@ GDBRemoteCommunication::DeallocateMemory (addr_t addr, uint32_t timeout_seconds)
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
{
if (!response.IsOKPacket())
if (response.IsOKPacket())
return true;
}
return false;

View File

@ -3615,18 +3615,20 @@ ClangASTContext::CreatePointerType (clang::ASTContext *ast, clang_type_t clang_t
}
clang_type_t
ClangASTContext::CreateLValueReferenceType (clang_type_t clang_type)
ClangASTContext::CreateLValueReferenceType (clang::ASTContext *ast,
clang_type_t clang_type)
{
if (clang_type)
return getASTContext()->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return ast->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return NULL;
}
clang_type_t
ClangASTContext::CreateRValueReferenceType (clang_type_t clang_type)
ClangASTContext::CreateRValueReferenceType (clang::ASTContext *ast,
clang_type_t clang_type)
{
if (clang_type)
return getASTContext()->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return ast->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return NULL;
}

View File

@ -709,13 +709,14 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
bool unwind_on_error = true;
bool keep_in_memory = false;
StreamString expr;
char path[PATH_MAX];
image_spec.GetPath(path, sizeof(path));
expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
ClangUserExpression::Evaluate (exe_ctx, keep_in_memory, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
@ -776,11 +777,12 @@ Process::UnloadImage (uint32_t image_token)
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
bool unwind_on_error = true;
bool keep_in_memory = false;
StreamString expr;
expr.Printf("dlclose ((void *)0x%llx)", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, keep_in_memory, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;

View File

@ -910,6 +910,7 @@ Target::EvaluateExpression
const char *expr_cstr,
StackFrame *frame,
bool unwind_on_error,
bool keep_in_memory,
lldb::ValueObjectSP &result_valobj_sp
)
{
@ -952,10 +953,32 @@ Target::EvaluateExpression
const_valobj_sp = result_valobj_sp->CreateConstantValue (exe_ctx.GetBestExecutionContextScope(),
persistent_variable_name);
lldb::ValueObjectSP live_valobj_sp = result_valobj_sp;
result_valobj_sp = const_valobj_sp;
ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
assert (clang_expr_variable_sp.get());
ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
assert (clang_expr_variable_sp.get());
// Set flags and live data as appropriate
const Value &result_value = live_valobj_sp->GetValue();
switch (result_value.GetValueType())
{
case Value::eValueTypeHostAddress:
case Value::eValueTypeFileAddress:
// we don't do anything with these for now
break;
case Value::eValueTypeScalar:
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
break;
case Value::eValueTypeLoadAddress:
clang_expr_variable_sp->m_live_sp = live_valobj_sp;
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
break;
}
}
else
{
@ -976,7 +999,8 @@ Target::EvaluateExpression
const char *prefix = GetExpressionPrefixContentsAsCString();
execution_results = ClangUserExpression::Evaluate (exe_ctx,
unwind_on_error,
unwind_on_error,
keep_in_memory,
expr_cstr,
prefix,
result_valobj_sp);