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
This commit is contained in:
Sean Callanan 2011-09-15 02:13:07 +00:00
parent 5acab501de
commit 3bfdaa2a47
27 changed files with 2343 additions and 523 deletions

View File

@ -97,13 +97,6 @@ public:
virtual clang::ASTConsumer * virtual clang::ASTConsumer *
ASTTransformer (clang::ASTConsumer *passthrough) = 0; ASTTransformer (clang::ASTConsumer *passthrough) = 0;
//------------------------------------------------------------------
/// Return the stream that the parser should use to write DWARF
/// opcodes.
//------------------------------------------------------------------
virtual StreamString &
DwarfOpcodeStream () = 0;
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Flags /// Flags
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -348,6 +348,130 @@ public:
lldb::addr_t lldb::addr_t
GetSymbolAddress (const ConstString &name); GetSymbolAddress (const ConstString &name);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Get basic target information.
///
/// @param[out] byte_order
/// The byte order of the target.
///
/// @param[out] address_byte_size
/// The size of a pointer in bytes.
///
/// @return
/// True if the information could be determined; false
/// otherwise.
//------------------------------------------------------------------
struct TargetInfo
{
lldb::ByteOrder byte_order;
size_t address_byte_size;
TargetInfo() :
byte_order(lldb::eByteOrderInvalid),
address_byte_size(0)
{
}
bool IsValid()
{
return (byte_order != lldb::eByteOrderInvalid &&
address_byte_size != 0);
}
};
TargetInfo GetTargetInfo();
//------------------------------------------------------------------
/// [Used by IRInterpreter] Write to the target.
///
/// @param[in] addr
/// The address to write to.
///
/// @param[in] data
/// The address of the data buffer to read from.
///
/// @param[in] length
/// The amount of data to write, in bytes.
///
/// @return
/// True if the write could be performed; false otherwise.
//------------------------------------------------------------------
bool
WriteTarget (lldb_private::Value &value,
const uint8_t *data,
size_t length);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Read from the target.
///
/// @param[in] data
/// The address of the data buffer to write to.
///
/// @param[in] addr
/// The address to read from.
///
/// @param[in] length
/// The amount of data to read, in bytes.
///
/// @return
/// True if the read could be performed; false otherwise.
//------------------------------------------------------------------
bool
ReadTarget (uint8_t *data,
lldb_private::Value &value,
size_t length);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Get the Value for a NamedDecl.
///
/// @param[in] decl
/// The Decl whose value is to be found.
///
/// @return
/// The value, or NULL.
//------------------------------------------------------------------
lldb_private::Value
LookupDecl (clang::NamedDecl *decl);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Returns true if the result is a
/// reference to data in the target, meaning it must be
/// dereferenced once more to get its data.
///
/// @param[in] name
/// The name of the result.
///
/// @return
/// True if the result is a reference; false otherwise (or on
/// error).
//------------------------------------------------------------------
bool
ResultIsReference (const ConstString &name);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Find the result persistent variable,
/// propagate the given value to it, and return it.
///
/// @param[out] valobj
/// Set to the complete object.
///
/// @param[in] value
/// A value indicating the location of the value's contents.
///
/// @param[in] name
/// The name of the result.
///
/// @param[in] type
/// The type of the data.
///
/// @return
/// True on success; false otherwise.
//------------------------------------------------------------------
bool
CompleteResultVariable (lldb::ClangExpressionVariableSP &valobj,
lldb_private::Value &value,
const ConstString &name,
lldb_private::TypeFromParser type);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// [Used by CommandObjectExpression] Materialize the entire struct /// [Used by CommandObjectExpression] Materialize the entire struct
/// at a given address, which should be aligned as specified by /// at a given address, which should be aligned as specified by
@ -596,6 +720,7 @@ private:
bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name. 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. bool m_ignore_lookups; ///< True during an import when we should be ignoring type lookups.
std::auto_ptr<ClangASTImporter> m_ast_importer; ///< The importer used to import types on the parser's behalf. std::auto_ptr<ClangASTImporter> m_ast_importer; ///< The importer used to import types on the parser's behalf.
TargetInfo m_target_info; ///< Basic information about the target.
private: private:
DISALLOW_COPY_AND_ASSIGN (ParserVars); DISALLOW_COPY_AND_ASSIGN (ParserVars);
}; };
@ -741,6 +866,29 @@ private:
FindGlobalDataSymbol (Target &target, FindGlobalDataSymbol (Target &target,
const ConstString &name); const ConstString &name);
//------------------------------------------------------------------
/// Given a target, find a variable that matches the given name and
/// type.
///
/// @param[in] target
/// The target to use as a basis for finding the variable.
///
/// @param[in] name
/// The name as a plain C string.
///
/// @param[in] type
/// The required type for the variable. This function may be called
/// during parsing, in which case we don't know its type; hence the
/// default.
///
/// @return
/// The LLDB Variable found, or NULL if none was found.
//------------------------------------------------------------------
lldb::VariableSP
FindGlobalVariable (Target &target,
const char *name,
TypeFromUser *type = NULL);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Get the value of a variable in a given execution context and return /// Get the value of a variable in a given execution context and return
/// the associated Types if needed. /// the associated Types if needed.

View File

@ -73,20 +73,8 @@ public:
Parse (Stream &stream); Parse (Stream &stream);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Convert the IR for an already-parsed expression to DWARF if possible. /// Ready an already-parsed expression for execution, possibly
/// /// evaluating it statically.
/// @param[in] dwarf_opcode_strm
/// The stream to place the resulting DWARF code into.
///
/// @return
/// An error code indicating the success or failure of the operation.
/// Test with Success().
//------------------------------------------------------------------
Error
MakeDWARF ();
//------------------------------------------------------------------
/// JIT-compile the IR for an already-parsed expression.
/// ///
/// @param[out] func_allocation_addr /// @param[out] func_allocation_addr
/// The address which can be used to deallocate the code for this /// The address which can be used to deallocate the code for this
@ -104,29 +92,35 @@ public:
/// The execution context to write the function into. /// The execution context to write the function into.
/// ///
/// @param[in] data_allocator /// @param[in] data_allocator
/// If non-NULL, he static data allocator to use for literal strings. /// If non-NULL, the static data allocator to use for literal strings.
///
/// @param[out] evaluated_statically
/// Set to true if the expression could be interpreted statically;
/// untouched otherwise.
/// ///
/// @param[out] const_result /// @param[out] const_result
/// If the result of the expression is constant, and the /// If the result of the expression is constant, and the
/// expression has no side effects, this is set to the result of the /// expression has no side effects, this is set to the result of the
/// expression. /// expression.
/// ///
/// @param[in] jit_only_if_needed /// @param[in] execution_policy
/// True if the expression must be compiled, regardless of whether a /// Determines whether the expression must be JIT-compiled, must be
/// constant result could be extracted from the IR or no. /// evaluated statically, or whether this decision may be made
/// opportunistically.
/// ///
/// @return /// @return
/// An error code indicating the success or failure of the operation. /// An error code indicating the success or failure of the operation.
/// Test with Success(). /// Test with Success().
//------------------------------------------------------------------ //------------------------------------------------------------------
Error Error
MakeJIT (lldb::addr_t &func_allocation_addr, PrepareForExecution (lldb::addr_t &func_allocation_addr,
lldb::addr_t &func_addr, lldb::addr_t &func_addr,
lldb::addr_t &func_end, lldb::addr_t &func_end,
ExecutionContext &exe_ctx, ExecutionContext &exe_ctx,
IRForTarget::StaticDataAllocator *data_allocator, IRForTarget::StaticDataAllocator *data_allocator,
lldb::ClangExpressionVariableSP &const_result, bool &evaluated_statically,
bool jit_only_if_needed = false); lldb::ClangExpressionVariableSP &const_result,
lldb_private::ExecutionPolicy execution_policy);
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Disassemble the machine code for a JITted function from the target /// Disassemble the machine code for a JITted function from the target

View File

@ -573,16 +573,6 @@ public:
clang::ASTConsumer * clang::ASTConsumer *
ASTTransformer (clang::ASTConsumer *passthrough); ASTTransformer (clang::ASTConsumer *passthrough);
//------------------------------------------------------------------
/// Return the stream that the parser should use to write DWARF
/// opcodes.
//------------------------------------------------------------------
StreamString &
DwarfOpcodeStream ()
{
return *((StreamString*)0);
}
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Return true if validation code should be inserted into the /// Return true if validation code should be inserted into the
/// expression. /// expression.

View File

@ -83,6 +83,9 @@ public:
/// The type that the expression should be coerced to. If NULL, /// The type that the expression should be coerced to. If NULL,
/// inferred from the expression itself. /// inferred from the expression itself.
/// ///
/// @param[in] execution_policy
/// Determines whether interpretation is possible or mandatory.
///
/// @param[in] keep_result_in_memory /// @param[in] keep_result_in_memory
/// True if the resulting persistent variable should reside in /// True if the resulting persistent variable should reside in
/// target memory, if applicable. /// target memory, if applicable.
@ -94,6 +97,7 @@ public:
Parse (Stream &error_stream, Parse (Stream &error_stream,
ExecutionContext &exe_ctx, ExecutionContext &exe_ctx,
TypeFromUser desired_type, TypeFromUser desired_type,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory); bool keep_result_in_memory);
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -226,13 +230,6 @@ public:
clang::ASTConsumer * clang::ASTConsumer *
ASTTransformer (clang::ASTConsumer *passthrough); ASTTransformer (clang::ASTConsumer *passthrough);
//------------------------------------------------------------------
/// Return the stream that the parser should use to write DWARF
/// opcodes.
//------------------------------------------------------------------
StreamString &
DwarfOpcodeStream ();
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Return true if validation code should be inserted into the /// Return true if validation code should be inserted into the
/// expression. /// expression.
@ -259,6 +256,10 @@ public:
/// @param[in] exe_ctx /// @param[in] exe_ctx
/// The execution context to use when evaluating the expression. /// The execution context to use when evaluating the expression.
/// ///
/// @param[in] execution_policy
/// Determines whether or not to try using the IR interpreter to
/// avoid running the expression on the parser.
///
/// @param[in] discard_on_error /// @param[in] discard_on_error
/// True if the thread's state should be restored in the case /// True if the thread's state should be restored in the case
/// of an error. /// of an error.
@ -278,6 +279,7 @@ public:
//------------------------------------------------------------------ //------------------------------------------------------------------
static ExecutionResults static ExecutionResults
Evaluate (ExecutionContext &exe_ctx, Evaluate (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error, bool discard_on_error,
const char *expr_cstr, const char *expr_cstr,
const char *expr_prefix, const char *expr_prefix,
@ -285,6 +287,7 @@ public:
static ExecutionResults static ExecutionResults
EvaluateWithError (ExecutionContext &exe_ctx, EvaluateWithError (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error, bool discard_on_error,
const char *expr_cstr, const char *expr_cstr,
const char *expr_prefix, const char *expr_prefix,
@ -307,6 +310,12 @@ private:
lldb::addr_t &object_ptr, lldb::addr_t &object_ptr,
lldb::addr_t &cmd_ptr); lldb::addr_t &cmd_ptr);
bool
EvaluatedStatically ()
{
return m_evaluated_statically;
}
std::string m_expr_text; ///< The text of the expression, as typed by the user std::string m_expr_text; ///< The text of the expression, as typed by the user
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
std::string m_transformed_text; ///< The text of the expression, as send to the parser std::string m_transformed_text; ///< The text of the expression, as send to the parser
@ -314,7 +323,6 @@ private:
std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression. std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF. std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF.
std::auto_ptr<StreamString> m_dwarf_opcodes; ///< The DWARF opcodes for the expression. May be NULL.
std::auto_ptr<ProcessDataAllocator> m_data_allocator; ///< The allocator that the parser uses to place strings for use by JIT-compiled code. std::auto_ptr<ProcessDataAllocator> m_data_allocator; ///< The allocator that the parser uses to place strings for use by JIT-compiled code.
bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
@ -323,6 +331,7 @@ private:
bool m_const_object; ///< True if "this" is const. bool m_const_object; ///< True if "this" is const.
Target *m_target; ///< The target for storing persistent data like types and variables. Target *m_target; ///< The target for storing persistent data like types and variables.
bool m_evaluated_statically; ///< True if the expression could be evaluated statically; false otherwise.
lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects. lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects.
}; };

View File

@ -148,16 +148,6 @@ public:
return NULL; return NULL;
} }
//------------------------------------------------------------------
/// Return the stream that the parser should use to write DWARF
/// opcodes.
//------------------------------------------------------------------
StreamString &
DwarfOpcodeStream ()
{
return *((StreamString*)NULL);
}
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Return true if validation code should be inserted into the /// Return true if validation code should be inserted into the
/// expression. /// expression.

View File

@ -73,6 +73,10 @@ public:
/// variables) should be resolved. If not, only external functions /// variables) should be resolved. If not, only external functions
/// are resolved. /// are resolved.
/// ///
/// @param[in] execution_policy
/// Determines whether an IR interpreter can be used to statically
/// evaluate the expression.
///
/// @param[in] const_result /// @param[in] const_result
/// This variable is populated with the statically-computed result /// This variable is populated with the statically-computed result
/// of the function, if it has no side-effects and the result can /// of the function, if it has no side-effects and the result can
@ -89,6 +93,7 @@ public:
//------------------------------------------------------------------ //------------------------------------------------------------------
IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars, bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result, lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator, StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream, lldb_private::Stream *error_stream,
@ -134,6 +139,18 @@ public:
virtual llvm::PassManagerType virtual llvm::PassManagerType
getPotentialPassManagerType() const; getPotentialPassManagerType() const;
//------------------------------------------------------------------
/// Checks whether the IR interpreter successfully interpreted the
/// expression.
///
/// Returns true if it did; false otherwise.
//------------------------------------------------------------------
bool
interpretSuccess ()
{
return m_interpret_success;
}
private: private:
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Ensures that the current function's linkage is set to external. /// Ensures that the current function's linkage is set to external.
@ -236,9 +253,11 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
/// Set the constant result variable m_const_result to the provided /// Find the NamedDecl corresponding to a Value. This interface is
/// constant, assuming it can be evaluated. The result variable /// exposed for the IR interpreter.
/// will be reset to NULL later if the expression has side effects. ///
/// @param[in] module
/// The module containing metadata to search
/// ///
/// @param[in] global /// @param[in] global
/// The global entity to search for /// The global entity to search for
@ -246,6 +265,10 @@ private:
/// @return /// @return
/// The corresponding variable declaration /// The corresponding variable declaration
//------------------------------------------------------------------ //------------------------------------------------------------------
public:
static clang::NamedDecl *
DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module);
private:
clang::NamedDecl * clang::NamedDecl *
DeclForGlobal (llvm::GlobalValue *global); DeclForGlobal (llvm::GlobalValue *global);
@ -549,8 +572,11 @@ private:
/// Flags /// Flags
bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
lldb_private::ExecutionPolicy m_execution_policy; ///< True if the interpreter should be used to attempt to get a static result
bool m_interpret_success; ///< True if the interpreter successfully handled the whole expression
std::string m_func_name; ///< The name of the function to translate 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::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...)
lldb_private::TypeFromParser m_result_type; ///< The type of the result variable.
llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet.
lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
StaticDataAllocator *m_data_allocator; ///< If non-NULL, the allocator to use for constant strings StaticDataAllocator *m_data_allocator; ///< If non-NULL, the allocator to use for constant strings

View File

@ -0,0 +1,107 @@
//===-- IRInterpreter.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_IRInterpreter_h_
#define liblldb_IRInterpreter_h_
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "llvm/Pass.h"
namespace llvm {
class Function;
class Module;
}
namespace lldb_private {
class ClangExpressionDeclMap;
}
//----------------------------------------------------------------------
/// @class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h"
/// @brief Attempt to interpret the function's code if it does not require
/// running the target.
///
/// In some cases, the IR for an expression can be evaluated entirely
/// in the debugger, manipulating variables but not executing any code
/// in the target. The IRInterpreter attempts to do this.
//----------------------------------------------------------------------
class IRInterpreter
{
public:
//------------------------------------------------------------------
/// Constructor
///
/// @param[in] decl_map
/// The list of externally-referenced variables for the expression,
/// for use in looking up globals and allocating the argument
/// struct. See the documentation for ClangExpressionDeclMap.
///
/// @param[in] error_stream
/// If non-NULL, a stream on which errors can be printed.
//------------------------------------------------------------------
IRInterpreter(lldb_private::ClangExpressionDeclMap &decl_map,
lldb_private::Stream *error_stream);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
~IRInterpreter();
//------------------------------------------------------------------
/// Run the IR interpreter on a single function
///
/// @param[in] result
/// This variable is populated with the return value of the
/// function, if it could be interpreted completely.
///
/// @param[in] result_name
/// The name of the result in the IR. If this name got a
/// value written to it as part of execution, then that value
/// will be used to create the result variable.
///
/// @param[in] result_type
/// The type of the result.
///
/// @param[in] llvm_function
/// The function to interpret.
///
/// @param[in] llvm_module
/// The module containing the function.
///
/// @return
/// True on success; false otherwise
//------------------------------------------------------------------
bool
maybeRunOnFunction (lldb::ClangExpressionVariableSP &result,
const lldb_private::ConstString &result_name,
lldb_private::TypeFromParser result_type,
llvm::Function &llvm_function,
llvm::Module &llvm_module);
private:
/// Flags
lldb_private::ClangExpressionDeclMap &m_decl_map; ///< The DeclMap containing the Decls
lldb_private::Stream *m_error_stream;
bool
supportsFunction (llvm::Function &llvm_function);
bool
runOnFunction (lldb::ClangExpressionVariableSP &result,
const lldb_private::ConstString &result_name,
lldb_private::TypeFromParser result_type,
llvm::Function &llvm_function,
llvm::Module &llvm_module);
};
#endif

View File

@ -600,6 +600,7 @@ public:
ExecutionResults ExecutionResults
EvaluateExpression (const char *expression, EvaluateExpression (const char *expression,
StackFrame *frame, StackFrame *frame,
lldb_private::ExecutionPolicy execution_policy,
bool unwind_on_error, bool unwind_on_error,
bool keep_in_memory, bool keep_in_memory,
lldb::DynamicValueType use_dynamic, lldb::DynamicValueType use_dynamic,

View File

@ -214,6 +214,15 @@ typedef enum FormatCategoryItem
eFormatCategoryItemRegexSynth = 0x0020 eFormatCategoryItemRegexSynth = 0x0020
} FormatCategoryItem; } FormatCategoryItem;
//------------------------------------------------------------------
/// Expression execution policies
//------------------------------------------------------------------
typedef enum {
eExecutionPolicyOnlyWhenNeeded,
eExecutionPolicyNever,
eExecutionPolicyAlways
} ExecutionPolicy;
} // namespace lldb } // namespace lldb

View File

@ -179,7 +179,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; }; 2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; };
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */; }; 2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */; };
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; }; 2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; };
2689006C13353E0E00698AC0 /* IRToDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */; };
2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */; }; 2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */; };
2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; }; 2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; };
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FA43171301048600E71120 /* FileSpec.cpp */; }; 2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FA43171301048600E71120 /* FileSpec.cpp */; };
@ -330,7 +329,6 @@
2689FFFB13353DB600698AC0 /* BreakpointLocationList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */; }; 2689FFFB13353DB600698AC0 /* BreakpointLocationList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */; };
2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */; }; 2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */; };
2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */; }; 2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */; };
268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; };
268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */ = {isa = PBXBuildFile; fileRef = 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */ = {isa = PBXBuildFile; fileRef = 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */; settings = {ATTRIBUTES = (Public, ); }; };
268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; }; 268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; };
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2690B3701381D5C300ECFBAE /* Memory.cpp */; }; 2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2690B3701381D5C300ECFBAE /* Memory.cpp */; };
@ -396,6 +394,9 @@
26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; }; 26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; }; 26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
26F73062139D8FDB00FD51C7 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F73061139D8FDB00FD51C7 /* History.cpp */; }; 26F73062139D8FDB00FD51C7 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F73061139D8FDB00FD51C7 /* History.cpp */; };
496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 496B015A1406DEB100F830D5 /* IRInterpreter.h */; };
49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 496B01581406DE8900F830D5 /* IRInterpreter.cpp */; };
49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; };
49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; }; 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; };
49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; }; 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; };
4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; }; 4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
@ -1104,6 +1105,8 @@
49445E341225AB6A00C11A81 /* ClangUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUserExpression.h; path = include/lldb/Expression/ClangUserExpression.h; sourceTree = "<group>"; }; 49445E341225AB6A00C11A81 /* ClangUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUserExpression.h; path = include/lldb/Expression/ClangUserExpression.h; sourceTree = "<group>"; };
495BBACB119A0DBE00418BEA /* PathMappingList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingList.cpp; path = source/Target/PathMappingList.cpp; sourceTree = "<group>"; }; 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingList.cpp; path = source/Target/PathMappingList.cpp; sourceTree = "<group>"; };
495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = "<group>"; }; 495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = "<group>"; };
496B01581406DE8900F830D5 /* IRInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRInterpreter.cpp; path = source/Expression/IRInterpreter.cpp; sourceTree = "<group>"; };
496B015A1406DEB100F830D5 /* IRInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRInterpreter.h; path = include/lldb/Expression/IRInterpreter.h; sourceTree = "<group>"; };
497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtilityFunction.cpp; path = source/Expression/ClangUtilityFunction.cpp; sourceTree = "<group>"; }; 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtilityFunction.cpp; path = source/Expression/ClangUtilityFunction.cpp; sourceTree = "<group>"; };
497C86C1122823F300B54702 /* ClangUtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtilityFunction.h; path = include/lldb/Expression/ClangUtilityFunction.h; sourceTree = "<group>"; }; 497C86C1122823F300B54702 /* ClangUtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtilityFunction.h; path = include/lldb/Expression/ClangUtilityFunction.h; sourceTree = "<group>"; };
497E7B331188ED300065CCA1 /* ABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABI.h; path = include/lldb/Target/ABI.h; sourceTree = "<group>"; }; 497E7B331188ED300065CCA1 /* ABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABI.h; path = include/lldb/Target/ABI.h; sourceTree = "<group>"; };
@ -1123,8 +1126,6 @@
49D7072811B5AD11001AD875 /* ClangASTSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTSource.cpp; path = source/Expression/ClangASTSource.cpp; sourceTree = "<group>"; }; 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTSource.cpp; path = source/Expression/ClangASTSource.cpp; sourceTree = "<group>"; };
49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTImporter.cpp; path = source/Symbol/ClangASTImporter.cpp; sourceTree = "<group>"; }; 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTImporter.cpp; path = source/Symbol/ClangASTImporter.cpp; sourceTree = "<group>"; };
49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = "<group>"; }; 49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = "<group>"; };
49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRToDWARF.cpp; path = source/Expression/IRToDWARF.cpp; sourceTree = "<group>"; };
49DA743411DE6BB2006AEF7E /* IRToDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRToDWARF.h; path = include/lldb/Expression/IRToDWARF.h; sourceTree = "<group>"; };
49E45FA911F660DC008F7B28 /* ClangASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTType.h; path = include/lldb/Symbol/ClangASTType.h; sourceTree = "<group>"; }; 49E45FA911F660DC008F7B28 /* ClangASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTType.h; path = include/lldb/Symbol/ClangASTType.h; sourceTree = "<group>"; };
49E45FAD11F660FE008F7B28 /* ClangASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTType.cpp; path = source/Symbol/ClangASTType.cpp; sourceTree = "<group>"; }; 49E45FAD11F660FE008F7B28 /* ClangASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTType.cpp; path = source/Symbol/ClangASTType.cpp; sourceTree = "<group>"; };
49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = "<group>"; }; 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = "<group>"; };
@ -2280,8 +2281,8 @@
49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */, 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
49307AB111DEA4F20081F992 /* IRForTarget.h */, 49307AB111DEA4F20081F992 /* IRForTarget.h */,
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */, 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
49DA743411DE6BB2006AEF7E /* IRToDWARF.h */, 496B015A1406DEB100F830D5 /* IRInterpreter.h */,
49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */, 496B01581406DE8900F830D5 /* IRInterpreter.cpp */,
4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */, 4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */,
4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */, 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */,
49C850761384A02F007DB519 /* ProcessDataAllocator.h */, 49C850761384A02F007DB519 /* ProcessDataAllocator.h */,
@ -2760,6 +2761,7 @@
isa = PBXHeadersBuildPhase; isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -3151,7 +3153,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */, 2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */,
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */, 2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */,
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */, 2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */,
2689006C13353E0E00698AC0 /* IRToDWARF.cpp in Sources */,
2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */, 2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */,
2689006E13353E1A00698AC0 /* File.cpp in Sources */, 2689006E13353E1A00698AC0 /* File.cpp in Sources */,
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */, 2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */,
@ -3361,11 +3362,12 @@
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */, 26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */,
94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */, 94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */,
949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */, 949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */,
268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */,
26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */, 26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */,
B27318421416AC12006039C8 /* WatchpointLocationList.cpp in Sources */, B27318421416AC12006039C8 /* WatchpointLocationList.cpp in Sources */,
26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */, 26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */,
B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */, B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -760,6 +760,7 @@ SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dyna
exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr,
m_opaque_sp.get(), m_opaque_sp.get(),
eExecutionPolicyOnlyWhenNeeded,
unwind_on_error, unwind_on_error,
keep_in_memory, keep_in_memory,
fetch_dynamic_value, fetch_dynamic_value,

View File

@ -379,7 +379,10 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression)
ValueObjectSP result_valobj_sp; ValueObjectSP result_valobj_sp;
m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression, m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(), m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(),
true, true, eNoDynamicValues, eExecutionPolicyAlways,
true, // unwind on error
true, // keep in memory
eNoDynamicValues,
result_valobj_sp); result_valobj_sp);
result_valobj_sp->SetName(ConstString(name)); result_valobj_sp->SetName(ConstString(name));
result = SBValue(result_valobj_sp); result = SBValue(result_valobj_sp);

View File

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

View File

@ -95,12 +95,13 @@ CommandObjectExpression::CommandOptions::SetOptionValue (uint32_t option_idx, co
break; break;
case 'u': case 'u':
bool success; {
unwind_on_error = Args::StringToBoolean(option_arg, true, &success); bool success;
if (!success) unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg); if (!success)
break; error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg);
break;
}
default: default:
error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
break; break;
@ -292,7 +293,13 @@ CommandObjectExpression::EvaluateExpression
break; break;
} }
exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, use_dynamic, result_valobj_sp); exe_results = m_exe_ctx.target->EvaluateExpression(expr,
m_exe_ctx.frame,
eExecutionPolicyOnlyWhenNeeded,
m_options.unwind_on_error,
keep_in_memory,
use_dynamic,
result_valobj_sp);
if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error) if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
{ {
@ -488,7 +495,6 @@ CommandObjectExpression::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_2, false, "dynamic-value", 'd', required_argument, NULL, 0, eArgTypeBoolean, "Upcast the value resulting from the expression to its dynamic type if available."}, { LLDB_OPT_SET_2, false, "dynamic-value", 'd', required_argument, NULL, 0, eArgTypeBoolean, "Upcast the value resulting from the expression to its dynamic type if available."},
{ LLDB_OPT_SET_ALL, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."}, { LLDB_OPT_SET_ALL, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
{ LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, { LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
{ LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, eArgTypeNone, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
}; };

View File

@ -82,6 +82,8 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx)
if (exe_ctx.target && !exe_ctx.target->GetScratchClangASTContext()) if (exe_ctx.target && !exe_ctx.target->GetScratchClangASTContext())
return false; return false;
m_parser_vars->m_target_info = GetTargetInfo();
return true; return true;
} }
@ -118,6 +120,29 @@ ClangExpressionDeclMap::DidParse()
// Interface for IRForTarget // Interface for IRForTarget
ClangExpressionDeclMap::TargetInfo
ClangExpressionDeclMap::GetTargetInfo()
{
assert (m_parser_vars.get());
TargetInfo ret;
ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
if (exe_ctx->process)
{
ret.byte_order = exe_ctx->process->GetByteOrder();
ret.address_byte_size = exe_ctx->process->GetAddressByteSize();
}
else if (exe_ctx->target)
{
ret.byte_order = exe_ctx->target->GetArchitecture().GetByteOrder();
ret.address_byte_size = exe_ctx->target->GetArchitecture().GetAddressByteSize();
}
return ret;
}
const ConstString & const ConstString &
ClangExpressionDeclMap::GetPersistentResultName () ClangExpressionDeclMap::GetPersistentResultName ()
{ {
@ -150,8 +175,8 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (), if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name, name,
user_type, user_type,
exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
exe_ctx->process->GetAddressByteSize())) m_parser_vars->m_target_info.address_byte_size))
return lldb::ClangExpressionVariableSP(); return lldb::ClangExpressionVariableSP();
ClangExpressionVariableSP pvar_sp (m_parser_vars->m_persistent_vars->GetVariable(name)); ClangExpressionVariableSP pvar_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
@ -165,8 +190,6 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
uint64_t value64 = value.getLimitedValue(); uint64_t value64 = value.getLimitedValue();
ByteOrder byte_order = exe_ctx->process->GetByteOrder();
size_t num_val_bytes = sizeof(value64); size_t num_val_bytes = sizeof(value64);
size_t num_data_bytes = pvar_sp->GetByteSize(); size_t num_data_bytes = pvar_sp->GetByteSize();
@ -182,7 +205,7 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
uint64_t mask = 0xffll << shift; uint64_t mask = 0xffll << shift;
uint8_t cur_byte = (uint8_t)((value64 & mask) >> shift); uint8_t cur_byte = (uint8_t)((value64 & mask) >> shift);
switch (byte_order) switch (m_parser_vars->m_target_info.byte_order)
{ {
case eByteOrderBig: case eByteOrderBig:
// High Low // High Low
@ -276,6 +299,59 @@ ClangExpressionDeclMap::BuildCastVariable (const ConstString &name,
return pvar_sp; return pvar_sp;
} }
bool
ClangExpressionDeclMap::ResultIsReference (const ConstString &name)
{
ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name);
return (pvar_sp->m_flags & ClangExpressionVariable::EVIsProgramReference);
}
bool
ClangExpressionDeclMap::CompleteResultVariable (lldb::ClangExpressionVariableSP &valobj,
lldb_private::Value &value,
const ConstString &name,
lldb_private::TypeFromParser type)
{
assert (m_parser_vars.get());
ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->GetVariable(name);
if (!pvar_sp)
return false;
if (pvar_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
!pvar_sp->m_live_sp)
{
// The reference comes from the program. We need to set up a live SP for it.
pvar_sp->m_live_sp = ValueObjectConstResult::Create(m_parser_vars->m_exe_ctx->GetBestExecutionContextScope(),
pvar_sp->GetTypeFromUser().GetASTContext(),
pvar_sp->GetTypeFromUser().GetOpaqueQualType(),
pvar_sp->GetName(),
value.GetScalar().ULongLong(),
value.GetValueAddressType(),
pvar_sp->GetByteSize());
}
if (pvar_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
{
pvar_sp->ValueUpdated();
const size_t pvar_byte_size = pvar_sp->GetByteSize();
uint8_t *pvar_data = pvar_sp->GetValueBytes();
if (!ReadTarget(pvar_data, value, pvar_byte_size))
return false;
pvar_sp->m_flags &= ~(ClangExpressionVariable::EVNeedsFreezeDry);
}
valobj = pvar_sp;
return true;
}
bool bool
ClangExpressionDeclMap::AddPersistentVariable ClangExpressionDeclMap::AddPersistentVariable
( (
@ -298,11 +374,14 @@ ClangExpressionDeclMap::AddPersistentVariable
parser_type.GetOpaqueQualType()), parser_type.GetOpaqueQualType()),
context); context);
if (!m_parser_vars->m_target_info.IsValid())
return false;
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (), if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name, name,
user_type, user_type,
exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
exe_ctx->process->GetAddressByteSize())) m_parser_vars->m_target_info.address_byte_size))
return false; return false;
ClangExpressionVariableSP var_sp (m_parser_vars->m_persistent_vars->GetVariable(name)); ClangExpressionVariableSP var_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
@ -653,6 +732,204 @@ ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name)
return GetSymbolAddress(*m_parser_vars->m_exe_ctx->target, name); return GetSymbolAddress(*m_parser_vars->m_exe_ctx->target, name);
} }
// Interface for IRInterpreter
bool
ClangExpressionDeclMap::WriteTarget (lldb_private::Value &value,
const uint8_t *data,
size_t length)
{
assert (m_parser_vars.get());
ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
if (value.GetContextType() == Value::eContextTypeRegisterInfo)
{
if (!exe_ctx->process)
return false;
RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
RegisterInfo *reg_info = value.GetRegisterInfo();
if (!reg_ctx)
return false;
lldb_private::RegisterValue reg_value;
Error err;
if (!reg_value.SetFromMemoryData (reg_info, data, length, exe_ctx->process->GetByteOrder(), err))
return false;
return reg_ctx->WriteRegister(reg_info, reg_value);
}
else
{
switch (value.GetValueType())
{
default:
return false;
case Value::eValueTypeFileAddress:
{
if (!exe_ctx->process)
return false;
Address file_addr;
if (!exe_ctx->target->GetImages().ResolveFileAddress((lldb::addr_t)value.GetScalar().ULongLong(), file_addr))
return false;
lldb::addr_t load_addr = file_addr.GetLoadAddress(exe_ctx->target);
Error err;
exe_ctx->process->WriteMemory(load_addr, data, length, err);
return err.Success();
}
case Value::eValueTypeLoadAddress:
{
if (!exe_ctx->process)
return false;
Error err;
exe_ctx->process->WriteMemory((lldb::addr_t)value.GetScalar().ULongLong(), data, length, err);
return err.Success();
}
case Value::eValueTypeHostAddress:
memcpy ((void *)value.GetScalar().ULongLong(), data, length);
return true;
case Value::eValueTypeScalar:
return false;
}
}
}
bool
ClangExpressionDeclMap::ReadTarget (uint8_t *data,
lldb_private::Value &value,
size_t length)
{
assert (m_parser_vars.get());
ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
if (value.GetContextType() == Value::eContextTypeRegisterInfo)
{
if (!exe_ctx->process)
return false;
RegisterContext *reg_ctx = exe_ctx->GetRegisterContext();
RegisterInfo *reg_info = value.GetRegisterInfo();
if (!reg_ctx)
return false;
lldb_private::RegisterValue reg_value;
Error err;
if (!reg_ctx->ReadRegister(reg_info, reg_value))
return false;
return reg_value.GetAsMemoryData(reg_info, data, length, exe_ctx->process->GetByteOrder(), err);
}
else
{
switch (value.GetValueType())
{
default:
return false;
case Value::eValueTypeFileAddress:
{
if (!exe_ctx->target)
return false;
Address file_addr;
if (!exe_ctx->target->GetImages().ResolveFileAddress((lldb::addr_t)value.GetScalar().ULongLong(), file_addr))
return false;
Error err;
exe_ctx->target->ReadMemory(file_addr, true, data, length, err);
return err.Success();
}
case Value::eValueTypeLoadAddress:
{
if (!exe_ctx->process)
return false;
Error err;
exe_ctx->process->ReadMemory((lldb::addr_t)value.GetScalar().ULongLong(), data, length, err);
return err.Success();
}
case Value::eValueTypeHostAddress:
memcpy (data, (const void *)value.GetScalar().ULongLong(), length);
return true;
case Value::eValueTypeScalar:
return false;
}
}
}
lldb_private::Value
ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
{
assert (m_parser_vars.get());
ExecutionContext exe_ctx = *m_parser_vars->m_exe_ctx;
ClangExpressionVariableSP expr_var_sp (m_found_entities.GetVariable(decl));
ClangExpressionVariableSP persistent_var_sp (m_parser_vars->m_persistent_vars->GetVariable(decl));
if (expr_var_sp)
{
const ConstString &name(expr_var_sp->GetName());
TypeFromUser type(expr_var_sp->GetTypeFromUser());
if (m_parser_vars->m_exe_ctx->frame)
{
VariableSP var(FindVariableInScope (*exe_ctx.frame, name, &type));
if (var)
return *GetVariableValue(exe_ctx, var, NULL);
}
if (m_parser_vars->m_exe_ctx->target)
{
VariableSP global(FindGlobalVariable (*exe_ctx.target, name.GetCString(), &type));
if (global)
return *GetVariableValue(exe_ctx, global, NULL);
lldb::addr_t location_load_addr = GetSymbolAddress(*exe_ctx.target, name);
if (location_load_addr != LLDB_INVALID_ADDRESS)
{
lldb_private::Value ret;
ret.SetValueType(Value::eValueTypeLoadAddress);
ret.SetContext(Value::eContextTypeInvalid, NULL);
ret.GetScalar() = location_load_addr;
return ret;
}
}
return Value();
}
else if (persistent_var_sp)
{
lldb_private::Value ret;
ret.SetValueType(Value::eValueTypeHostAddress);
ret.SetContext(Value::eContextTypeInvalid, NULL);
ret.GetScalar() = (lldb::addr_t)persistent_var_sp->GetValueBytes();
return ret;
}
else
{
return Value();
}
}
// Interface for CommandObjectExpression // Interface for CommandObjectExpression
bool bool
@ -1630,8 +1907,8 @@ ClangExpressionDeclMap::FindGlobalDataSymbol
SymbolContextList sc_list; SymbolContextList sc_list;
target.GetImages().FindSymbolsWithNameAndType(name, target.GetImages().FindSymbolsWithNameAndType(name,
eSymbolTypeData, eSymbolTypeData,
sc_list); sc_list);
if (sc_list.GetSize()) if (sc_list.GetSize())
{ {
@ -1644,7 +1921,67 @@ ClangExpressionDeclMap::FindGlobalDataSymbol
return NULL; return NULL;
} }
// This is a callback used with Variable::GetValuesForVariableExpressionPath
static uint32_t GetVariableCallback (void *baton,
const char *name,
VariableList &variable_list)
{
Target *target = static_cast<Target *>(baton);
if (target)
{
return target->GetImages().FindGlobalVariables (ConstString(name),
true,
UINT32_MAX,
variable_list);
}
return 0;
}
lldb::VariableSP
ClangExpressionDeclMap::FindGlobalVariable
(
Target &target,
const char *name,
TypeFromUser *type
)
{
VariableList vars;
ValueObjectList valobjs;
Error error (Variable::GetValuesForVariableExpressionPath (name,
&target,
GetVariableCallback,
&target,
vars,
valobjs));
if (vars.GetSize())
{
if (type)
{
for (size_t i = 0; i < vars.GetSize(); ++i)
{
VariableSP var_sp = vars.GetVariableAtIndex(i);
if (type->GetASTContext() == var_sp->GetType()->GetClangAST())
{
if (ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var_sp->GetType()->GetClangFullType()))
return var_sp;
}
}
}
else
{
return vars.GetVariableAtIndex(0);
}
}
return VariableSP();
}
// Interface for ClangASTSource // Interface for ClangASTSource
void void
ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name) ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name)
{ {
@ -1656,10 +1993,6 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (log) if (log)
log->Printf("Hunting for a definition for '%s'", name.GetCString()); log->Printf("Hunting for a definition for '%s'", name.GetCString());
// Back out in all cases where we're not fully initialized
if (m_parser_vars->m_exe_ctx->frame == NULL)
return;
if (m_parser_vars->m_ignore_lookups) if (m_parser_vars->m_ignore_lookups)
{ {
if (log) if (log)
@ -1740,19 +2073,37 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
ValueObjectSP valobj; ValueObjectSP valobj;
VariableSP var; VariableSP var;
Error err; Error err;
bool found = false;
valobj = m_parser_vars->m_exe_ctx->frame->GetValueForVariableExpressionPath(name_unique_cstr, if (m_parser_vars->m_exe_ctx->frame)
eNoDynamicValues,
StackFrame::eExpressionPathOptionCheckPtrVsMember,
var,
err);
// If we found a variable in scope, no need to pull up function names
if (err.Success() && var != NULL)
{ {
AddOneVariable(context, var); valobj = m_parser_vars->m_exe_ctx->frame->GetValueForVariableExpressionPath(name_unique_cstr,
eNoDynamicValues,
StackFrame::eExpressionPathOptionCheckPtrVsMember,
var,
err);
// If we found a variable in scope, no need to pull up function names
if (err.Success() && var != NULL)
{
AddOneVariable(context, var);
found = true;
}
} }
else else if (m_parser_vars->m_exe_ctx->target)
{
var = FindGlobalVariable(*m_parser_vars->m_exe_ctx->target,
name_unique_cstr,
NULL);
if (var)
{
AddOneVariable(context, var);
found = true;
}
}
if (!found)
{ {
const bool include_symbols = true; const bool include_symbols = true;
const bool append = false; const bool append = false;
@ -1781,6 +2132,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (!found_specific) if (!found_specific)
AddOneFunction(context, sym_ctx.function, NULL); AddOneFunction(context, sym_ctx.function, NULL);
found_specific = true; found_specific = true;
found = true;
} }
else if (sym_ctx.symbol) else if (sym_ctx.symbol)
{ {
@ -1794,12 +2146,19 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (!found_specific) if (!found_specific)
{ {
if (generic_symbol) if (generic_symbol)
{
AddOneFunction (context, NULL, generic_symbol); AddOneFunction (context, NULL, generic_symbol);
found = true;
}
else if (non_extern_symbol) else if (non_extern_symbol)
{
AddOneFunction (context, NULL, non_extern_symbol); AddOneFunction (context, NULL, non_extern_symbol);
found = true;
}
} }
} }
else
if (!found)
{ {
// We couldn't find a variable or function for this. Now we'll hunt for a generic // We couldn't find a variable or function for this. Now we'll hunt for a generic
// data symbol, and -- if it is found -- treat it as a variable. // data symbol, and -- if it is found -- treat it as a variable.
@ -1807,7 +2166,10 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
Symbol *data_symbol = FindGlobalDataSymbol(*m_parser_vars->m_exe_ctx->target, name); Symbol *data_symbol = FindGlobalDataSymbol(*m_parser_vars->m_exe_ctx->target, name);
if (data_symbol) if (data_symbol)
{
AddOneGenericVariable(context, *data_symbol); AddOneGenericVariable(context, *data_symbol);
found = true;
}
} }
} }
@ -1834,10 +2196,14 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
else else
{ {
static ConstString g_lldb_class_name ("$__lldb_class"); static ConstString g_lldb_class_name ("$__lldb_class");
if (name == g_lldb_class_name) if (name == g_lldb_class_name)
{ {
// Clang is looking for the type of "this" // Clang is looking for the type of "this"
if (!m_parser_vars->m_exe_ctx->frame)
return;
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false); VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars) if (!vars)
@ -1900,6 +2266,9 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
{ {
// Clang is looking for the type of "*self" // Clang is looking for the type of "*self"
if (!m_parser_vars->m_exe_ctx->frame)
return;
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false); VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars) if (!vars)
@ -2213,8 +2582,11 @@ ClangExpressionDeclMap::GetVariableValue
lldb::addr_t load_addr = so_addr.GetLoadAddress(exe_ctx.target); lldb::addr_t load_addr = so_addr.GetLoadAddress(exe_ctx.target);
var_location->GetScalar() = load_addr; if (load_addr != LLDB_INVALID_ADDRESS)
var_location->SetValueType(Value::eValueTypeLoadAddress); {
var_location->GetScalar() = load_addr;
var_location->SetValueType(Value::eValueTypeLoadAddress);
}
} }
if (user_type) if (user_type)
@ -2248,8 +2620,8 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (), ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
entity_name, entity_name,
ut, ut,
m_parser_vars->m_exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_exe_ctx->process->GetAddressByteSize())); m_parser_vars->m_target_info.address_byte_size));
assert (entity.get()); assert (entity.get());
entity->EnableParserVars(); entity->EnableParserVars();
entity->m_parser_vars->m_parser_type = pt; entity->m_parser_vars->m_parser_type = pt;
@ -2331,8 +2703,8 @@ ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (), ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
entity_name, entity_name,
user_type, user_type,
m_parser_vars->m_exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_exe_ctx->process->GetAddressByteSize())); m_parser_vars->m_target_info.address_byte_size));
assert (entity.get()); assert (entity.get());
std::auto_ptr<Value> symbol_location(new Value); std::auto_ptr<Value> symbol_location(new Value);
@ -2449,8 +2821,8 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType()); NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope(), ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope(),
m_parser_vars->m_exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_exe_ctx->process->GetAddressByteSize())); m_parser_vars->m_target_info.address_byte_size));
assert (entity.get()); assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString()); std::string decl_name(context.m_decl_name.getAsString());
entity->SetName (ConstString (decl_name.c_str())); entity->SetName (ConstString (decl_name.c_str()));
@ -2547,8 +2919,8 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
fun_location->GetScalar() = load_addr; fun_location->GetScalar() = load_addr;
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (), ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
m_parser_vars->m_exe_ctx->process->GetByteOrder(), m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_exe_ctx->process->GetAddressByteSize())); m_parser_vars->m_target_info.address_byte_size));
assert (entity.get()); assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString()); std::string decl_name(context.m_decl_name.getAsString());
entity->SetName(ConstString(decl_name.c_str())); entity->SetName(ConstString(decl_name.c_str()));

View File

@ -19,7 +19,6 @@
#include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/IRToDWARF.h"
#include "lldb/Expression/RecordingMemoryManager.h" #include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h"
@ -418,66 +417,14 @@ static bool FindFunctionInModule (std::string &mangled_name,
} }
Error Error
ClangExpressionParser::MakeDWARF () ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
{ lldb::addr_t &func_addr,
Error err; lldb::addr_t &func_end,
ExecutionContext &exe_ctx,
llvm::Module *module = m_code_generator->GetModule(); IRForTarget::StaticDataAllocator *data_allocator,
bool &evaluated_statically,
if (!module) lldb::ClangExpressionVariableSP &const_result,
{ ExecutionPolicy execution_policy)
err.SetErrorToGenericError();
err.SetErrorString("IR doesn't contain a module");
return err;
}
ClangExpressionVariableList *local_variables = m_expr.LocalVariables();
ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
if (!local_variables)
{
err.SetErrorToGenericError();
err.SetErrorString("Can't convert an expression without a VariableList to DWARF");
return err;
}
if (!decl_map)
{
err.SetErrorToGenericError();
err.SetErrorString("Can't convert an expression without a DeclMap to DWARF");
return err;
}
std::string function_name;
if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
return err;
}
IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream(), function_name.c_str());
if (!ir_to_dwarf.runOnModule(*module))
{
err.SetErrorToGenericError();
err.SetErrorString("Couldn't convert the expression to DWARF");
return err;
}
err.Clear();
return err;
}
Error
ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
lldb::addr_t &func_addr,
lldb::addr_t &func_end,
ExecutionContext &exe_ctx,
IRForTarget::StaticDataAllocator *data_allocator,
lldb::ClangExpressionVariableSP &const_result,
bool jit_only_if_needed)
{ {
func_allocation_addr = LLDB_INVALID_ADDRESS; func_allocation_addr = LLDB_INVALID_ADDRESS;
func_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS;
@ -522,6 +469,7 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
IRForTarget ir_for_target(decl_map, IRForTarget ir_for_target(decl_map,
m_expr.NeedsVariableResolution(), m_expr.NeedsVariableResolution(),
execution_policy,
const_result, const_result,
data_allocator, data_allocator,
error_stream, error_stream,
@ -530,17 +478,25 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
if (!ir_for_target.runOnModule(*module)) if (!ir_for_target.runOnModule(*module))
{ {
err.SetErrorToGenericError(); err.SetErrorToGenericError();
err.SetErrorString("Couldn't convert the expression to DWARF"); err.SetErrorString("Couldn't prepare the expression for execution in the target");
return err; return err;
} }
if (jit_only_if_needed && const_result.get()) if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess())
{ {
evaluated_statically = true;
err.Clear(); err.Clear();
return err; return err;
} }
if (m_expr.NeedsValidation() && exe_ctx.process->GetDynamicCheckers()) if (!exe_ctx.process || execution_policy == eExecutionPolicyNever)
{
err.SetErrorToGenericError();
err.SetErrorString("Execution needed to run in the target, but the target can't be run");
return err;
}
if (m_expr.NeedsValidation() && exe_ctx.process && exe_ctx.process->GetDynamicCheckers())
{ {
IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str()); IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str());

View File

@ -253,7 +253,16 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
lldb::ClangExpressionVariableSP const_result; lldb::ClangExpressionVariableSP const_result;
Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, NULL, const_result)); bool evaluated_statically = false; // should stay that way
Error jit_error (m_parser->PrepareForExecution (m_jit_alloc,
m_jit_start_addr,
m_jit_end_addr,
exe_ctx,
NULL,
evaluated_statically,
const_result,
eExecutionPolicyAlways));
if (!jit_error.Success()) if (!jit_error.Success())
return false; return false;

View File

@ -53,6 +53,7 @@ ClangUserExpression::ClangUserExpression (const char *expr,
m_objectivec (false), m_objectivec (false),
m_needs_object_ptr (false), m_needs_object_ptr (false),
m_const_object (false), m_const_object (false),
m_evaluated_statically (false),
m_const_result (), m_const_result (),
m_target (NULL) m_target (NULL)
{ {
@ -167,6 +168,7 @@ bool
ClangUserExpression::Parse (Stream &error_stream, ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx, ExecutionContext &exe_ctx,
TypeFromUser desired_type, TypeFromUser desired_type,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory) bool keep_result_in_memory)
{ {
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -279,39 +281,23 @@ ClangUserExpression::Parse (Stream &error_stream,
return false; 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); if (execution_policy != eExecutionPolicyNever && exe_ctx.process)
m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder()); m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
m_local_variables.reset(new ClangExpressionVariableList()); 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);
Error dwarf_error = parser.MakeDWARF (); if (log && m_data_allocator.get())
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)
{ {
StreamString dump_string; StreamString dump_string;
m_data_allocator->Dump(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. // 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)); lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (m_dwarf_opcodes.get()) if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
{
// 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)
{ {
lldb::addr_t struct_address; lldb::addr_t struct_address;
@ -594,38 +572,31 @@ ClangUserExpression::Execute (Stream &error_stream,
} }
else 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; return eExecutionSetupError;
} }
} }
StreamString &
ClangUserExpression::DwarfOpcodeStream ()
{
if (!m_dwarf_opcodes.get())
m_dwarf_opcodes.reset(new StreamString());
return *m_dwarf_opcodes.get();
}
ExecutionResults ExecutionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error, bool discard_on_error,
const char *expr_cstr, const char *expr_cstr,
const char *expr_prefix, const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp) lldb::ValueObjectSP &result_valobj_sp)
{ {
Error error; 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 ExecutionResults
ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx, ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
bool discard_on_error, lldb_private::ExecutionPolicy execution_policy,
const char *expr_cstr, bool discard_on_error,
const char *expr_prefix, const char *expr_cstr,
lldb::ValueObjectSP &result_valobj_sp, const char *expr_prefix,
Error &error) lldb::ValueObjectSP &result_valobj_sp,
Error &error)
{ {
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); 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) 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); error.SetErrorString ("expression needed to run but couldn't");
return eExecutionSetupError;
return execution_results;
}
} }
if (!exe_ctx.process->GetDynamicCheckers()) if (execution_policy != eExecutionPolicyNever && !exe_ctx.process->GetDynamicCheckers())
{ {
if (log) if (log)
log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers =="); log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
@ -672,7 +648,9 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
if (log) if (log)
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); 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()) if (error_stream.GetString().empty())
error.SetErrorString ("expression failed to parse, unknown error"); error.SetErrorString ("expression failed to parse, unknown error");
@ -683,14 +661,26 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
{ {
lldb::ClangExpressionVariableSP expr_result; lldb::ClangExpressionVariableSP expr_result;
if (user_expression_sp->m_const_result.get()) if (user_expression_sp->EvaluatedStatically())
{ {
if (log) if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant =="); 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; 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 else
{ {
error_stream.GetString().clear(); error_stream.GetString().clear();

View File

@ -128,8 +128,16 @@ ClangUtilityFunction::Install (Stream &error_stream,
lldb::ClangExpressionVariableSP const_result; lldb::ClangExpressionVariableSP const_result;
bool evaluated_statically = false; // should stay that way
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), const_result); Error jit_error = parser.PrepareForExecution (m_jit_alloc,
m_jit_start_addr,
m_jit_end_addr,
exe_ctx,
m_data_allocator.get(),
evaluated_statically,
const_result,
eExecutionPolicyAlways);
if (log) if (log)
{ {

View File

@ -1,4 +1,4 @@
//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===// //===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -26,6 +26,7 @@
#include "lldb/Core/Scalar.h" #include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h" #include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h" #include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTContext.h"
@ -45,12 +46,15 @@ IRForTarget::StaticDataAllocator::~StaticDataAllocator()
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars, bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result, lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator, StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream, lldb_private::Stream *error_stream,
const char *func_name) : const char *func_name) :
ModulePass(ID), ModulePass(ID),
m_resolve_vars(resolve_vars), m_resolve_vars(resolve_vars),
m_execution_policy(execution_policy),
m_interpret_success(false),
m_func_name(func_name), m_func_name(func_name),
m_module(NULL), m_module(NULL),
m_decl_map(decl_map), m_decl_map(decl_map),
@ -309,12 +313,13 @@ IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
return true; return true;
} }
clang::NamedDecl * clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val) IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
{ {
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
if (!named_metadata) if (!named_metadata)
return NULL; return NULL;
@ -350,6 +355,12 @@ IRForTarget::DeclForGlobal (GlobalValue *global_val)
return NULL; return NULL;
} }
clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val)
{
return DeclForGlobal(global_val, m_module);
}
void void
IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer, IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
const lldb_private::ConstString &name, const lldb_private::ConstString &name,
@ -554,8 +565,6 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
// Get the next available result name from m_decl_map and create the persistent // Get the next available result name from m_decl_map and create the persistent
// variable for it // variable for it
lldb_private::TypeFromParser result_decl_type;
// If the result is an Lvalue, it is emitted as a pointer; see // If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult. // ASTResultSynthesizer::SynthesizeBodyResult.
if (m_result_is_pointer) if (m_result_is_pointer)
@ -577,19 +586,19 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
result_decl_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext()); &result_decl->getASTContext());
} }
else else
{ {
result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext()); &result_decl->getASTContext());
} }
if (log) if (log)
{ {
lldb_private::StreamString type_desc_stream; lldb_private::StreamString type_desc_stream;
result_decl_type.DumpTypeDescription(&type_desc_stream); m_result_type.DumpTypeDescription(&type_desc_stream);
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str()); log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str());
} }
@ -665,7 +674,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{ {
MaybeSetConstantResult (initializer, MaybeSetConstantResult (initializer,
m_result_name, m_result_name,
result_decl_type); m_result_type);
} }
StoreInst *synthesized_store = new StoreInst(initializer, StoreInst *synthesized_store = new StoreInst(initializer,
@ -677,9 +686,9 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
} }
else else
{ {
if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (result_decl_type.GetOpaqueQualType())) if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (m_result_type.GetOpaqueQualType()))
{ {
MaybeSetCastResult (result_decl_type); MaybeSetCastResult (m_result_type);
} }
result_global->replaceAllUsesWith(new_result_global); result_global->replaceAllUsesWith(new_result_global);
@ -688,7 +697,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
if (!m_const_result) if (!m_const_result)
m_decl_map->AddPersistentVariable(result_decl, m_decl_map->AddPersistentVariable(result_decl,
m_result_name, m_result_name,
result_decl_type, m_result_type,
true, true,
m_result_is_pointer); m_result_is_pointer);
@ -2247,6 +2256,9 @@ IRForTarget::BuildRelocation(llvm::Type *type,
bool bool
IRForTarget::CompleteDataAllocation () IRForTarget::CompleteDataAllocation ()
{ {
if (!m_data_allocator)
return true;
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_data_allocator->GetStream().GetSize()) if (!m_data_allocator->GetStream().GetSize())
@ -2336,8 +2348,48 @@ IRForTarget::runOnModule (Module &llvm_module)
return false; return false;
} }
if (m_const_result) if (m_const_result && m_execution_policy != lldb_private::eExecutionPolicyAlways)
{
m_interpret_success = true;
return true; return true;
}
for (bbi = function->begin();
bbi != function->end();
++bbi)
{
if (!RemoveGuards(*bbi))
{
if (log)
log->Printf("RemoveGuards() failed");
// RemoveGuards() reports its own errors, so we don't do so here
return false;
}
if (!RewritePersistentAllocs(*bbi))
{
if (log)
log->Printf("RewritePersistentAllocs() failed");
// RewritePersistentAllocs() reports its own errors, so we don't do so here
return false;
}
}
if (m_decl_map && m_execution_policy != lldb_private::eExecutionPolicyAlways)
{
IRInterpreter interpreter (*m_decl_map,
m_error_stream);
if (interpreter.maybeRunOnFunction(m_const_result, m_result_name, m_result_type, *function, llvm_module))
{
m_interpret_success = true;
return true;
}
}
if (log) if (log)
{ {
@ -2379,34 +2431,10 @@ IRForTarget::runOnModule (Module &llvm_module)
return false; return false;
} }
//////////////////////////////////
// Run basic-block level passes
//
for (bbi = function->begin(); for (bbi = function->begin();
bbi != function->end(); bbi != function->end();
++bbi) ++bbi)
{ {
if (!RemoveGuards(*bbi))
{
if (log)
log->Printf("RemoveGuards() failed");
// RemoveGuards() reports its own errors, so we don't do so here
return false;
}
if (!RewritePersistentAllocs(*bbi))
{
if (log)
log->Printf("RewritePersistentAllocs() failed");
// RewritePersistentAllocs() reports its own errors, so we don't do so here
return false;
}
if (!RewriteObjCSelectors(*bbi)) if (!RewriteObjCSelectors(*bbi))
{ {
if (log) if (log)

File diff suppressed because it is too large Load Diff

View File

@ -1,219 +0,0 @@
//===-- IRToDWARF.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Expression/IRToDWARF.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/InstrTypes.h"
#include "llvm/Module.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include <map>
using namespace llvm;
static char ID;
IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars,
lldb_private::ClangExpressionDeclMap *decl_map,
lldb_private::StreamString &strm,
const char *func_name) :
ModulePass(ID),
m_func_name(func_name),
m_local_vars(local_vars),
m_decl_map(decl_map),
m_strm(strm)
{
}
IRToDWARF::~IRToDWARF()
{
}
class Relocator
{
public:
Relocator()
{
}
~Relocator()
{
}
void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
{
m_basic_blocks[bb] = offset;
}
bool BasicBlockIsMarked(BasicBlock *bb)
{
return m_basic_blocks.find(bb) != m_basic_blocks.end();
}
void MarkRelocation(BasicBlock *bb, uint16_t offset)
{
m_relocations[offset] = bb;
}
bool ResolveRelocations(lldb_private::StreamString &strm)
{
std::map<uint16_t, BasicBlock*>::const_iterator iter;
lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
// This array must be delete [] d at every exit
size_t temporary_bufsize = strm.GetSize();
uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
for (iter = m_relocations.begin();
iter != m_relocations.end();
++iter)
{
const std::pair<uint16_t, BasicBlock*> &pair = *iter;
uint16_t off = pair.first;
BasicBlock *bb = pair.second;
if (m_basic_blocks.find(bb) == m_basic_blocks.end())
{
delete [] temporary_buffer;
return false;
}
uint16_t target_off = m_basic_blocks[bb];
int16_t relative = (int16_t)target_off - (int16_t)off;
swapper.Clear();
swapper << relative;
// off is intended to be the offset of the branch opcode (which is
// what the relative location is added to) so
// (temporary_buffer + off + 1) skips the opcode and writes to the
// relative location
memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
}
strm.Clear();
strm.Write(temporary_buffer, temporary_bufsize);
delete [] temporary_buffer;
return true;
}
private:
std::map<BasicBlock*, uint16_t> m_basic_blocks;
std::map<uint16_t, BasicBlock*> m_relocations;
};
bool
IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
{
///////////////////////////////////////
// Mark the current block as visited
//
size_t stream_size = m_strm.GetSize();
if (stream_size > 0xffff)
return false;
uint16_t offset = stream_size & 0xffff;
R.MarkBasicBlock(&BB, offset);
////////////////////////////////////////////////
// Translate the current basic block to DWARF
//
/////////////////////////////////////////////////
// Visit all successors we haven't visited yet
//
TerminatorInst *arnold = BB.getTerminator();
if (!arnold)
return false;
unsigned successor_index;
unsigned num_successors = arnold->getNumSuccessors();
for (successor_index = 0;
successor_index < num_successors;
++successor_index)
{
BasicBlock *successor = arnold->getSuccessor(successor_index);
if (!R.BasicBlockIsMarked(successor))
{
if (!runOnBasicBlock(*successor, R))
return false;
}
}
return true;
}
bool
IRToDWARF::runOnModule(Module &M)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
if (!function)
{
if (log)
log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
return false;
}
Relocator relocator;
if (!runOnBasicBlock(function->getEntryBlock(), relocator))
return false;
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream oss(s);
M.print(oss, NULL);
oss.flush();
log->Printf ("Module being translated to DWARF: \n%s", s.c_str());
}
// TEMPORARY: Fail in order to force execution in the target.
return false;
return relocator.ResolveRelocations(m_strm);
}
void
IRToDWARF::assignPassManager(PMStack &PMS,
PassManagerType T)
{
}
PassManagerType
IRToDWARF::getPotentialPassManagerType() const
{
return PMT_ModulePassManager;
}

View File

@ -117,7 +117,8 @@ clang::Decl
{ {
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to); ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
to_interface_decl->setExternallyCompleted(); if (!to_interface_decl->isForwardDecl())
to_interface_decl->setExternallyCompleted();
} }
return clang::ASTImporter::Imported(from, to); return clang::ASTImporter::Imported(from, to);

View File

@ -1154,7 +1154,7 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
expr.Printf("dlopen (\"%s\", 2)", path); expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n"; const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp; lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp); ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
error = result_valobj_sp->GetError(); error = result_valobj_sp->GetError();
if (error.Success()) if (error.Success())
{ {
@ -1218,7 +1218,7 @@ Process::UnloadImage (uint32_t image_token)
expr.Printf("dlclose ((void *)0x%llx)", image_addr); expr.Printf("dlclose ((void *)0x%llx)", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp; lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp); ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success()) if (result_valobj_sp->GetError().Success())
{ {
Scalar scalar; Scalar scalar;

View File

@ -194,11 +194,12 @@ public:
const bool discard_on_error = true; const bool discard_on_error = true;
Error error; Error error;
result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx, result_code = ClangUserExpression::EvaluateWithError (context.exe_ctx,
discard_on_error, eExecutionPolicyAlways,
bp_loc_sp->GetConditionText(), discard_on_error,
NULL, bp_loc_sp->GetConditionText(),
result_value_sp, NULL,
error); result_value_sp,
error);
if (result_code == eExecutionCompleted) if (result_code == eExecutionCompleted)
{ {
if (result_value_sp) if (result_value_sp)

View File

@ -1133,6 +1133,7 @@ Target::EvaluateExpression
( (
const char *expr_cstr, const char *expr_cstr,
StackFrame *frame, StackFrame *frame,
lldb_private::ExecutionPolicy execution_policy,
bool unwind_on_error, bool unwind_on_error,
bool keep_in_memory, bool keep_in_memory,
lldb::DynamicValueType use_dynamic, lldb::DynamicValueType use_dynamic,
@ -1244,6 +1245,7 @@ Target::EvaluateExpression
const char *prefix = GetExpressionPrefixContentsAsCString(); const char *prefix = GetExpressionPrefixContentsAsCString();
execution_results = ClangUserExpression::Evaluate (exe_ctx, execution_results = ClangUserExpression::Evaluate (exe_ctx,
execution_policy,
unwind_on_error, unwind_on_error,
expr_cstr, expr_cstr,
prefix, prefix,