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 *
ASTTransformer (clang::ASTConsumer *passthrough) = 0;
//------------------------------------------------------------------
/// Return the stream that the parser should use to write DWARF
/// opcodes.
//------------------------------------------------------------------
virtual StreamString &
DwarfOpcodeStream () = 0;
//------------------------------------------------------------------
/// Flags
//------------------------------------------------------------------

View File

@ -348,6 +348,130 @@ public:
lldb::addr_t
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
/// 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_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.
TargetInfo m_target_info; ///< Basic information about the target.
private:
DISALLOW_COPY_AND_ASSIGN (ParserVars);
};
@ -741,6 +866,29 @@ private:
FindGlobalDataSymbol (Target &target,
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
/// the associated Types if needed.

View File

@ -73,20 +73,8 @@ public:
Parse (Stream &stream);
//------------------------------------------------------------------
/// Convert the IR for an already-parsed expression to DWARF if possible.
///
/// @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.
/// Ready an already-parsed expression for execution, possibly
/// evaluating it statically.
///
/// @param[out] func_allocation_addr
/// The address which can be used to deallocate the code for this
@ -104,30 +92,36 @@ public:
/// The execution context to write the function into.
///
/// @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
/// If the result of the expression is constant, and the
/// expression has no side effects, this is set to the result of the
/// expression.
///
/// @param[in] jit_only_if_needed
/// True if the expression must be compiled, regardless of whether a
/// constant result could be extracted from the IR or no.
/// @param[in] execution_policy
/// Determines whether the expression must be JIT-compiled, must be
/// evaluated statically, or whether this decision may be made
/// opportunistically.
///
/// @return
/// An error code indicating the success or failure of the operation.
/// Test with Success().
//------------------------------------------------------------------
Error
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 = false);
PrepareForExecution (lldb::addr_t &func_allocation_addr,
lldb::addr_t &func_addr,
lldb::addr_t &func_end,
ExecutionContext &exe_ctx,
IRForTarget::StaticDataAllocator *data_allocator,
bool &evaluated_statically,
lldb::ClangExpressionVariableSP &const_result,
lldb_private::ExecutionPolicy execution_policy);
//------------------------------------------------------------------
/// Disassemble the machine code for a JITted function from the target
/// process's memory and print the result to a stream.

View File

@ -573,16 +573,6 @@ public:
clang::ASTConsumer *
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
/// expression.

View File

@ -83,6 +83,9 @@ public:
/// The type that the expression should be coerced to. If NULL,
/// inferred from the expression itself.
///
/// @param[in] execution_policy
/// Determines whether interpretation is possible or mandatory.
///
/// @param[in] keep_result_in_memory
/// True if the resulting persistent variable should reside in
/// target memory, if applicable.
@ -94,6 +97,7 @@ public:
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory);
//------------------------------------------------------------------
@ -226,13 +230,6 @@ public:
clang::ASTConsumer *
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
/// expression.
@ -259,6 +256,10 @@ public:
/// @param[in] exe_ctx
/// 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
/// True if the thread's state should be restored in the case
/// of an error.
@ -277,14 +278,16 @@ public:
/// A Process::ExecutionResults value. eExecutionCompleted for success.
//------------------------------------------------------------------
static ExecutionResults
Evaluate (ExecutionContext &exe_ctx,
Evaluate (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
static ExecutionResults
EvaluateWithError (ExecutionContext &exe_ctx,
EvaluateWithError (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
@ -307,6 +310,12 @@ private:
lldb::addr_t &object_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_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
@ -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<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.
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.
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.
};

View File

@ -148,16 +148,6 @@ public:
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
/// expression.

View File

@ -73,6 +73,10 @@ public:
/// variables) should be resolved. If not, only external functions
/// are resolved.
///
/// @param[in] execution_policy
/// Determines whether an IR interpreter can be used to statically
/// evaluate the expression.
///
/// @param[in] const_result
/// This variable is populated with the statically-computed result
/// of the function, if it has no side-effects and the result can
@ -89,6 +93,7 @@ public:
//------------------------------------------------------------------
IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream,
@ -133,6 +138,18 @@ public:
//------------------------------------------------------------------
virtual llvm::PassManagerType
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:
//------------------------------------------------------------------
@ -236,16 +253,22 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
/// Set the constant result variable m_const_result to the provided
/// constant, assuming it can be evaluated. The result variable
/// will be reset to NULL later if the expression has side effects.
/// Find the NamedDecl corresponding to a Value. This interface is
/// exposed for the IR interpreter.
///
/// @param[in] module
/// The module containing metadata to search
///
/// @param[in] global
/// The global entity to search for
///
/// @return
/// The corresponding variable declaration
//------------------------------------------------------------------
//------------------------------------------------------------------
public:
static clang::NamedDecl *
DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module);
private:
clang::NamedDecl *
DeclForGlobal (llvm::GlobalValue *global);
@ -549,8 +572,11 @@ private:
/// Flags
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
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.
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

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
EvaluateExpression (const char *expression,
StackFrame *frame,
lldb_private::ExecutionPolicy execution_policy,
bool unwind_on_error,
bool keep_in_memory,
lldb::DynamicValueType use_dynamic,

View File

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

View File

@ -179,7 +179,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; };
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.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 */; };
2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.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 */; };
2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1110F1B83100F91463 /* BreakpointOptions.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, ); }; };
268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.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 */; };
26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
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 */; };
49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; };
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>"; };
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>"; };
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>"; };
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>"; };
@ -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>"; };
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>"; };
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>"; };
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>"; };
@ -2280,8 +2281,8 @@
49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
49307AB111DEA4F20081F992 /* IRForTarget.h */,
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
49DA743411DE6BB2006AEF7E /* IRToDWARF.h */,
49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */,
496B015A1406DEB100F830D5 /* IRInterpreter.h */,
496B01581406DE8900F830D5 /* IRInterpreter.cpp */,
4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */,
4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */,
49C850761384A02F007DB519 /* ProcessDataAllocator.h */,
@ -2760,6 +2761,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
496B015B1406DEB100F830D5 /* IRInterpreter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3151,7 +3153,6 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */,
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */,
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */,
2689006C13353E0E00698AC0 /* IRToDWARF.cpp in Sources */,
2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */,
2689006E13353E1A00698AC0 /* File.cpp in Sources */,
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */,
@ -3361,11 +3362,12 @@
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */,
94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */,
949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */,
268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */,
26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */,
B27318421416AC12006039C8 /* WatchpointLocationList.cpp in Sources */,
26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */,
B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

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

View File

@ -379,7 +379,10 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression)
ValueObjectSP result_valobj_sp;
m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
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->SetName(ConstString(name));
result = SBValue(result_valobj_sp);

View File

@ -199,7 +199,9 @@ BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, 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.
return NULL;

View File

@ -95,12 +95,13 @@ CommandObjectExpression::CommandOptions::SetOptionValue (uint32_t option_idx, co
break;
case 'u':
bool success;
unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg);
break;
{
bool success;
unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
if (!success)
error.SetErrorStringWithFormat("Could not convert \"%s\" to a boolean value.", option_arg);
break;
}
default:
error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
break;
@ -292,7 +293,13 @@ CommandObjectExpression::EvaluateExpression
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)
{
@ -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_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, "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 }
};

View File

@ -82,6 +82,8 @@ ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx)
if (exe_ctx.target && !exe_ctx.target->GetScratchClangASTContext())
return false;
m_parser_vars->m_target_info = GetTargetInfo();
return true;
}
@ -118,6 +120,29 @@ ClangExpressionDeclMap::DidParse()
// 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 &
ClangExpressionDeclMap::GetPersistentResultName ()
{
@ -146,12 +171,12 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
type.GetASTContext(),
type.GetOpaqueQualType()),
context);
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name,
user_type,
exe_ctx->process->GetByteOrder(),
exe_ctx->process->GetAddressByteSize()))
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size))
return lldb::ClangExpressionVariableSP();
ClangExpressionVariableSP pvar_sp (m_parser_vars->m_persistent_vars->GetVariable(name));
@ -164,9 +189,7 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
return lldb::ClangExpressionVariableSP();
uint64_t value64 = value.getLimitedValue();
ByteOrder byte_order = exe_ctx->process->GetByteOrder();
size_t num_val_bytes = sizeof(value64);
size_t num_data_bytes = pvar_sp->GetByteSize();
@ -182,7 +205,7 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
uint64_t mask = 0xffll << shift;
uint8_t cur_byte = (uint8_t)((value64 & mask) >> shift);
switch (byte_order)
switch (m_parser_vars->m_target_info.byte_order)
{
case eByteOrderBig:
// High Low
@ -276,6 +299,59 @@ ClangExpressionDeclMap::BuildCastVariable (const ConstString &name,
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
ClangExpressionDeclMap::AddPersistentVariable
(
@ -297,12 +373,15 @@ ClangExpressionDeclMap::AddPersistentVariable
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
if (!m_parser_vars->m_target_info.IsValid())
return false;
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
name,
user_type,
exe_ctx->process->GetByteOrder(),
exe_ctx->process->GetAddressByteSize()))
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size))
return false;
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);
}
// 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
bool
@ -1630,8 +1907,8 @@ ClangExpressionDeclMap::FindGlobalDataSymbol
SymbolContextList sc_list;
target.GetImages().FindSymbolsWithNameAndType(name,
eSymbolTypeData,
sc_list);
eSymbolTypeData,
sc_list);
if (sc_list.GetSize())
{
@ -1644,7 +1921,67 @@ ClangExpressionDeclMap::FindGlobalDataSymbol
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
void
ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString &name)
{
@ -1656,10 +1993,6 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (log)
log->Printf("Hunting for a definition for '%s'", name.GetCString());
// Back out in all cases where we're not fully initialized
if (m_parser_vars->m_exe_ctx->frame == NULL)
return;
if (m_parser_vars->m_ignore_lookups)
{
if (log)
@ -1740,19 +2073,37 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
ValueObjectSP valobj;
VariableSP var;
Error err;
bool found = false;
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)
if (m_parser_vars->m_exe_ctx->frame)
{
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 append = false;
@ -1781,6 +2132,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (!found_specific)
AddOneFunction(context, sym_ctx.function, NULL);
found_specific = true;
found = true;
}
else if (sym_ctx.symbol)
{
@ -1794,12 +2146,19 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
if (!found_specific)
{
if (generic_symbol)
{
AddOneFunction (context, NULL, generic_symbol);
found = true;
}
else if (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
// 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);
if (data_symbol)
{
AddOneGenericVariable(context, *data_symbol);
found = true;
}
}
}
@ -1829,15 +2191,19 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
NamespaceDecl *clang_namespace_decl = AddNamespace(context, namespace_decl);
if (clang_namespace_decl)
clang_namespace_decl->setHasExternalLexicalStorage();
}
}
}
else
{
static ConstString g_lldb_class_name ("$__lldb_class");
if (name == g_lldb_class_name)
{
// 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);
if (!vars)
@ -1900,6 +2266,9 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
{
// 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);
if (!vars)
@ -2213,8 +2582,11 @@ ClangExpressionDeclMap::GetVariableValue
lldb::addr_t load_addr = so_addr.GetLoadAddress(exe_ctx.target);
var_location->GetScalar() = load_addr;
var_location->SetValueType(Value::eValueTypeLoadAddress);
if (load_addr != LLDB_INVALID_ADDRESS)
{
var_location->GetScalar() = load_addr;
var_location->SetValueType(Value::eValueTypeLoadAddress);
}
}
if (user_type)
@ -2229,7 +2601,7 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
assert (m_parser_vars.get());
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
TypeFromUser ut;
TypeFromParser pt;
@ -2248,8 +2620,8 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP v
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx->GetBestExecutionContextScope (),
entity_name,
ut,
m_parser_vars->m_exe_ctx->process->GetByteOrder(),
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
entity->EnableParserVars();
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 (),
entity_name,
user_type,
m_parser_vars->m_exe_ctx->process->GetByteOrder(),
m_parser_vars->m_exe_ctx->process->GetAddressByteSize()));
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::auto_ptr<Value> symbol_location(new Value);
@ -2449,8 +2821,8 @@ ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
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_exe_ctx->process->GetAddressByteSize()));
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName (ConstString (decl_name.c_str()));
@ -2547,8 +2919,8 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
fun_location->GetScalar() = load_addr;
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_exe_ctx->process->GetAddressByteSize()));
m_parser_vars->m_target_info.byte_order,
m_parser_vars->m_target_info.address_byte_size));
assert (entity.get());
std::string decl_name(context.m_decl_name.getAsString());
entity->SetName(ConstString(decl_name.c_str()));

View File

@ -19,7 +19,6 @@
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/IRToDWARF.h"
#include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
@ -418,66 +417,14 @@ static bool FindFunctionInModule (std::string &mangled_name,
}
Error
ClangExpressionParser::MakeDWARF ()
{
Error err;
llvm::Module *module = m_code_generator->GetModule();
if (!module)
{
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)
ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
lldb::addr_t &func_addr,
lldb::addr_t &func_end,
ExecutionContext &exe_ctx,
IRForTarget::StaticDataAllocator *data_allocator,
bool &evaluated_statically,
lldb::ClangExpressionVariableSP &const_result,
ExecutionPolicy execution_policy)
{
func_allocation_addr = LLDB_INVALID_ADDRESS;
func_addr = LLDB_INVALID_ADDRESS;
@ -520,8 +467,9 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
if (exe_ctx.target)
error_stream = &exe_ctx.target->GetDebugger().GetErrorStream();
IRForTarget ir_for_target(decl_map,
IRForTarget ir_for_target(decl_map,
m_expr.NeedsVariableResolution(),
execution_policy,
const_result,
data_allocator,
error_stream,
@ -530,17 +478,25 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
if (!ir_for_target.runOnModule(*module))
{
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;
}
if (jit_only_if_needed && const_result.get())
if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess())
{
evaluated_statically = true;
err.Clear();
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());

View File

@ -253,7 +253,16 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
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())
return false;

View File

@ -53,6 +53,7 @@ ClangUserExpression::ClangUserExpression (const char *expr,
m_objectivec (false),
m_needs_object_ptr (false),
m_const_object (false),
m_evaluated_statically (false),
m_const_result (),
m_target (NULL)
{
@ -167,6 +168,7 @@ bool
ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -279,39 +281,23 @@ ClangUserExpression::Parse (Stream &error_stream,
return false;
}
///////////////////////////////////////////////
// Convert the output of the parser to DWARF
//////////////////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically if possible
//
m_dwarf_opcodes.reset(new StreamString);
m_dwarf_opcodes->SetByteOrder (lldb::endian::InlHostByteOrder());
m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
m_local_variables.reset(new ClangExpressionVariableList());
Error dwarf_error = parser.MakeDWARF ();
if (dwarf_error.Success())
{
if (log)
log->Printf("Code can be interpreted.");
m_expr_decl_map->DidParse();
return true;
}
if (execution_policy != eExecutionPolicyNever && exe_ctx.process)
m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
//////////////////////////////////
// JIT the output of the parser
//
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);
m_dwarf_opcodes.reset();
m_data_allocator.reset(new ProcessDataAllocator(*exe_ctx.process));
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), m_const_result, true);
if (log)
if (log && m_data_allocator.get())
{
StreamString dump_string;
m_data_allocator->Dump(dump_string);
@ -505,15 +491,7 @@ ClangUserExpression::Execute (Stream &error_stream,
// expression, it's quite convenient to have these logs come out with the STEP log as well.
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (m_dwarf_opcodes.get())
{
// TODO execute the JITted opcodes
error_stream.Printf("We don't currently support executing DWARF expressions");
return eExecutionSetupError;
}
else if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
{
lldb::addr_t struct_address;
@ -594,38 +572,31 @@ ClangUserExpression::Execute (Stream &error_stream,
}
else
{
error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
return eExecutionSetupError;
}
}
StreamString &
ClangUserExpression::DwarfOpcodeStream ()
{
if (!m_dwarf_opcodes.get())
m_dwarf_opcodes.reset(new StreamString());
return *m_dwarf_opcodes.get();
}
ExecutionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp)
{
Error error;
return EvaluateWithError (exe_ctx, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
return EvaluateWithError (exe_ctx, execution_policy, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error);
}
ExecutionResults
ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error)
ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool discard_on_error,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error)
{
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@ -633,13 +604,18 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
if (exe_ctx.process == NULL || exe_ctx.process->GetState() != lldb::eStateStopped)
{
error.SetErrorString ("must have a stopped process to evaluate expressions.");
if (execution_policy == eExecutionPolicyAlways)
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
return eExecutionSetupError;
error.SetErrorString ("expression needed to run but couldn't");
return execution_results;
}
}
if (!exe_ctx.process->GetDynamicCheckers())
if (execution_policy != eExecutionPolicyNever && !exe_ctx.process->GetDynamicCheckers())
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Installing dynamic checkers ==");
@ -672,7 +648,9 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true))
const bool keep_expression_in_memory = true;
if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), execution_policy, keep_expression_in_memory))
{
if (error_stream.GetString().empty())
error.SetErrorString ("expression failed to parse, unknown error");
@ -683,14 +661,26 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
{
lldb::ClangExpressionVariableSP expr_result;
if (user_expression_sp->m_const_result.get())
if (user_expression_sp->EvaluatedStatically())
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
if (user_expression_sp->m_const_result)
result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
else
error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
execution_results = eExecutionCompleted;
}
else if (execution_policy == eExecutionPolicyNever)
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
if (error_stream.GetString().empty())
error.SetErrorString ("expression needed to run but couldn't");
}
else
{
error_stream.GetString().clear();

View File

@ -128,8 +128,16 @@ ClangUtilityFunction::Install (Stream &error_stream,
lldb::ClangExpressionVariableSP const_result;
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), const_result);
bool evaluated_statically = false; // should stay that way
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)
{

View File

@ -1,4 +1,4 @@
//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===//
//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -26,6 +26,7 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
@ -45,12 +46,15 @@ IRForTarget::StaticDataAllocator::~StaticDataAllocator()
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
StaticDataAllocator *data_allocator,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
m_resolve_vars(resolve_vars),
m_execution_policy(execution_policy),
m_interpret_success(false),
m_func_name(func_name),
m_module(NULL),
m_decl_map(decl_map),
@ -309,12 +313,13 @@ IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
return true;
}
clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val)
IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
{
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)
return NULL;
@ -350,6 +355,12 @@ IRForTarget::DeclForGlobal (GlobalValue *global_val)
return NULL;
}
clang::NamedDecl *
IRForTarget::DeclForGlobal (GlobalValue *global_val)
{
return DeclForGlobal(global_val, m_module);
}
void
IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
const lldb_private::ConstString &name,
@ -553,9 +564,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
// Get the next available result name from m_decl_map and create the persistent
// variable for it
lldb_private::TypeFromParser result_decl_type;
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
if (m_result_is_pointer)
@ -577,19 +586,19 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
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());
}
else
{
result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
}
if (log)
{
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());
}
@ -665,7 +674,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
MaybeSetConstantResult (initializer,
m_result_name,
result_decl_type);
m_result_type);
}
StoreInst *synthesized_store = new StoreInst(initializer,
@ -677,9 +686,9 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
}
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);
@ -688,7 +697,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
if (!m_const_result)
m_decl_map->AddPersistentVariable(result_decl,
m_result_name,
result_decl_type,
m_result_type,
true,
m_result_is_pointer);
@ -2247,6 +2256,9 @@ IRForTarget::BuildRelocation(llvm::Type *type,
bool
IRForTarget::CompleteDataAllocation ()
{
if (!m_data_allocator)
return true;
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_data_allocator->GetStream().GetSize())
@ -2335,9 +2347,49 @@ IRForTarget::runOnModule (Module &llvm_module)
return false;
}
if (m_const_result)
if (m_const_result && m_execution_policy != lldb_private::eExecutionPolicyAlways)
{
m_interpret_success = 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)
{
@ -2379,34 +2431,10 @@ IRForTarget::runOnModule (Module &llvm_module)
return false;
}
//////////////////////////////////
// Run basic-block level passes
//
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 (!RewriteObjCSelectors(*bbi))
{
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);
to_interface_decl->setExternallyCompleted();
if (!to_interface_decl->isForwardDecl())
to_interface_decl->setExternallyCompleted();
}
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);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
error = result_valobj_sp->GetError();
if (error.Success())
{
@ -1218,7 +1218,7 @@ Process::UnloadImage (uint32_t image_token)
expr.Printf("dlclose ((void *)0x%llx)", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
ClangUserExpression::Evaluate (exe_ctx, eExecutionPolicyAlways, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;

View File

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

View File

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