diff options
author | Sean Callanan <scallanan@apple.com> | 2011-09-15 02:13:07 +0000 |
---|---|---|
committer | Sean Callanan <scallanan@apple.com> | 2011-09-15 02:13:07 +0000 |
commit | 3bfdaa2a4735262a1d246ced4db906a3531ba330 (patch) | |
tree | 8ff56a95ada43dd7cee0482eb3400462c7eb9054 /lldb/source/Expression/ClangUserExpression.cpp | |
parent | 5acab501de113acb4c0d28b48e76c27631ba0904 (diff) | |
download | bcm5719-llvm-3bfdaa2a4735262a1d246ced4db906a3531ba330.tar.gz bcm5719-llvm-3bfdaa2a4735262a1d246ced4db906a3531ba330.zip |
This patch modifies the expression parser to allow it
to execute expressions even in the absence of a process.
This allows expressions to run in situations where the
target cannot run -- e.g., to perform calculations based
on type information, or to inspect a binary's static
data.
This modification touches the following files:
lldb-private-enumerations.h
Introduce a new enum specifying the policy for
processing an expression. Some expressions should
always be JITted, for example if they are functions
that will be used over and over again. Some
expressions should always be interpreted, for
example if the target is unsafe to run. For most,
it is acceptable to JIT them, but interpretation
is preferable when possible.
Target.[h,cpp]
Have EvaluateExpression now accept the new enum.
ClangExpressionDeclMap.[cpp,h]
Add support for the IR interpreter and also make
the ClangExpressionDeclMap more robust in the
absence of a process.
ClangFunction.[cpp,h]
Add support for the new enum.
IRInterpreter.[cpp,h]
New implementation.
ClangUserExpression.[cpp,h]
Add support for the new enum, and for running
expressions in the absence of a process.
ClangExpression.h
Remove references to the old DWARF-based method
of evaluating expressions, because it has been
superseded for now.
ClangUtilityFunction.[cpp,h]
Add support for the new enum.
ClangExpressionParser.[cpp,h]
Add support for the new enum, remove references
to DWARF, and add support for checking whether
the expression could be evaluated statically.
IRForTarget.[h,cpp]
Add support for the new enum, and add utility
functions to support the interpreter.
IRToDWARF.cpp
Removed
CommandObjectExpression.cpp
Remove references to the obsolete -i option.
Process.cpp
Modify calls to ClangUserExpression::Evaluate
to pass the correct enum (for dlopen/dlclose)
SBValue.cpp
Add support for the new enum.
SBFrame.cpp
Add support for he new enum.
BreakpointOptions.cpp
Add support for the new enum.
llvm-svn: 139772
Diffstat (limited to 'lldb/source/Expression/ClangUserExpression.cpp')
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 122 |
1 files changed, 56 insertions, 66 deletions
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 1a81c24efc0..dd5af2a30ed 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -53,6 +53,7 @@ ClangUserExpression::ClangUserExpression (const char *expr, m_objectivec (false), m_needs_object_ptr (false), m_const_object (false), + m_evaluated_statically (false), m_const_result (), m_target (NULL) { @@ -167,6 +168,7 @@ bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, TypeFromUser desired_type, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -279,39 +281,23 @@ ClangUserExpression::Parse (Stream &error_stream, return false; } - /////////////////////////////////////////////// - // Convert the output of the parser to DWARF + ////////////////////////////////////////////////////////////////////////////////////////// + // Prepare the output of the parser for execution, evaluating it statically if possible // - - m_dwarf_opcodes.reset(new StreamString); - m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder()); - m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary); - - m_local_variables.reset(new ClangExpressionVariableList()); - - Error dwarf_error = parser.MakeDWARF (); - - if (dwarf_error.Success()) - { - if (log) - log->Printf("Code can be interpreted."); - m_expr_decl_map->DidParse(); - - return true; - } - - ////////////////////////////////// - // JIT the output of the parser - // - - m_dwarf_opcodes.reset(); - - m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process)); - - Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), m_const_result, true); - - if (log) + if (execution_policy != eExecutionPolicyNever && exe_ctx.process) + m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process)); + + Error jit_error = parser.PrepareForExecution (m_jit_alloc, + m_jit_start_addr, + m_jit_end_addr, + exe_ctx, + m_data_allocator.get(), + m_evaluated_statically, + m_const_result, + execution_policy); + + if (log && m_data_allocator.get()) { StreamString dump_string; m_data_allocator->Dump(dump_string); @@ -505,15 +491,7 @@ ClangUserExpression::Execute (Stream &error_stream, // expression, it's quite convenient to have these logs come out with the STEP log as well. lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - if (m_dwarf_opcodes.get()) - { - // TODO execute the JITted opcodes - - error_stream.Printf("We don't currently support executing DWARF expressions"); - - return eExecutionSetupError; - } - else if (m_jit_start_addr != LLDB_INVALID_ADDRESS) + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { lldb::addr_t struct_address; @@ -594,38 +572,31 @@ ClangUserExpression::Execute (Stream &error_stream, } else { - error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present"); + error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); return eExecutionSetupError; } } -StreamString & -ClangUserExpression::DwarfOpcodeStream () -{ - if (!m_dwarf_opcodes.get()) - m_dwarf_opcodes.reset(new StreamString()); - - return *m_dwarf_opcodes.get(); -} - ExecutionResults -ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, +ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool discard_on_error, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { Error error; - return EvaluateWithError (exe_ctx, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error); + return EvaluateWithError (exe_ctx, execution_policy, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error); } ExecutionResults -ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, - bool discard_on_error, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error) +ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool discard_on_error, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + Error &error) { lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -633,13 +604,18 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped) { - error.SetErrorString ("must have a stopped process to evaluate expressions."); + if (execution_policy == eExecutionPolicyAlways) + { + if (log) + log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - result_valobj_sp = ValueObjectConstResult::Create (NULL, error); - return eExecutionSetupError; + error.SetErrorString ("expression needed to run but couldn't"); + + return execution_results; + } } - - if (!exe_ctx.process->GetDynamicCheckers()) + + if (execution_policy != eExecutionPolicyNever && !exe_ctx.process->GetDynamicCheckers()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers =="); @@ -672,7 +648,9 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); - if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true)) + const bool keep_expression_in_memory = true; + + if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), execution_policy, keep_expression_in_memory)) { if (error_stream.GetString().empty()) error.SetErrorString ("expression failed to parse, unknown error"); @@ -683,14 +661,26 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, { lldb::ClangExpressionVariableSP expr_result; - if (user_expression_sp->m_const_result.get()) + if (user_expression_sp->EvaluatedStatically()) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant =="); - result_valobj_sp = user_expression_sp->m_const_result->GetValueObject(); + if (user_expression_sp->m_const_result) + result_valobj_sp = user_expression_sp->m_const_result->GetValueObject(); + else + error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); + execution_results = eExecutionCompleted; } + else if (execution_policy == eExecutionPolicyNever) + { + if (log) + log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); + + if (error_stream.GetString().empty()) + error.SetErrorString ("expression needed to run but couldn't"); + } else { error_stream.GetString().clear(); |