summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Expression/ClangExpression.h17
-rw-r--r--lldb/include/lldb/Expression/ClangExpressionParser.h59
-rw-r--r--lldb/include/lldb/Expression/ClangUserExpression.h2
-rw-r--r--lldb/include/lldb/Expression/ClangUtilityFunction.h2
-rw-r--r--lldb/include/lldb/Expression/IRExecutionUnit.h512
-rw-r--r--lldb/include/lldb/Expression/IRForTarget.h32
-rw-r--r--lldb/include/lldb/Expression/ProcessDataAllocator.h72
-rw-r--r--lldb/include/lldb/Expression/RecordingMemoryManager.h424
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj18
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp292
-rw-r--r--lldb/source/Expression/ClangFunction.cpp7
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp19
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp14
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp770
-rw-r--r--lldb/source/Expression/IRForTarget.cpp60
-rw-r--r--lldb/source/Expression/ProcessDataAllocator.cpp43
-rw-r--r--lldb/source/Expression/RecordingMemoryManager.cpp342
17 files changed, 1371 insertions, 1314 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpression.h b/lldb/include/lldb/Expression/ClangExpression.h
index ac29024804e..07a9ca096f2 100644
--- a/lldb/include/lldb/Expression/ClangExpression.h
+++ b/lldb/include/lldb/Expression/ClangExpression.h
@@ -48,7 +48,6 @@ public:
ClangExpression () :
m_jit_process_wp(),
- m_jit_alloc (LLDB_INVALID_ADDRESS),
m_jit_start_addr (LLDB_INVALID_ADDRESS),
m_jit_end_addr (LLDB_INVALID_ADDRESS)
{
@@ -59,7 +58,6 @@ public:
//------------------------------------------------------------------
virtual ~ClangExpression ()
{
- DeallocateJITFunction ();
}
//------------------------------------------------------------------
@@ -140,20 +138,6 @@ public:
virtual bool
NeedsVariableResolution () = 0;
- void
- DeallocateJITFunction ()
- {
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
- if (jit_process_sp && m_jit_alloc != LLDB_INVALID_ADDRESS)
- {
- jit_process_sp->DeallocateMemory (m_jit_alloc);
- // If this process is ever used for anything else, we can not clear it
- // here. For now it is only used in order to deallocate any code if
- // m_jit_alloc is a valid address.
- m_jit_alloc = LLDB_INVALID_ADDRESS;
- }
- }
-
//------------------------------------------------------------------
/// Return the address of the function's JIT-compiled code, or
/// LLDB_INVALID_ADDRESS if the function is not JIT compiled
@@ -167,7 +151,6 @@ public:
protected:
lldb::ProcessWP m_jit_process_wp;
- lldb::addr_t m_jit_alloc; ///< The address of the block containing JITted code. LLDB_INVALID_ADDRESS if invalid.
lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
diff --git a/lldb/include/lldb/Expression/ClangExpressionParser.h b/lldb/include/lldb/Expression/ClangExpressionParser.h
index c3323b88e13..57172c5e3ab 100644
--- a/lldb/include/lldb/Expression/ClangExpressionParser.h
+++ b/lldb/include/lldb/Expression/ClangExpressionParser.h
@@ -22,7 +22,7 @@
namespace lldb_private
{
-class RecordingMemoryManager;
+class IRExecutionUnit;
//----------------------------------------------------------------------
/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
@@ -76,10 +76,6 @@ public:
/// 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
- /// JIT'ed function
- ///
/// @param[out] func_addr
/// The address to which the function has been written.
///
@@ -91,9 +87,6 @@ public:
/// @param[in] exe_ctx
/// The execution context to write the function into.
///
- /// @param[in] data_allocator
- /// 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.
@@ -113,11 +106,9 @@ public:
/// Test with Success().
//------------------------------------------------------------------
Error
- PrepareForExecution (lldb::addr_t &func_allocation_addr,
- lldb::addr_t &func_addr,
+ PrepareForExecution (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);
@@ -137,49 +128,9 @@ public:
//------------------------------------------------------------------
Error
DisassembleFunction (Stream &stream,
- ExecutionContext &exe_ctx,
- RecordingMemoryManager *jit_memory_manager);
+ ExecutionContext &exe_ctx);
private:
- //----------------------------------------------------------------------
- /// @class JittedFunction ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
- /// @brief Encapsulates a single function that has been generated by the JIT.
- ///
- /// Functions that have been generated by the JIT are first resident in the
- /// local process, and then placed in the target process. JittedFunction
- /// represents a function possibly resident in both.
- //----------------------------------------------------------------------
- struct JittedFunction {
- std::string m_name; ///< The function's name
- lldb::addr_t m_local_addr; ///< The address of the function in LLDB's memory
- lldb::addr_t m_remote_addr; ///< The address of the function in the target's memory
-
- //------------------------------------------------------------------
- /// Constructor
- ///
- /// Initializes class variabes.
- ///
- /// @param[in] name
- /// The name of the function.
- ///
- /// @param[in] local_addr
- /// The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
- /// it is not present in LLDB's memory.
- ///
- /// @param[in] remote_addr
- /// The address of the function in the target, or LLDB_INVALID_ADDRESS
- /// if it is not present in the target's memory.
- //------------------------------------------------------------------
- JittedFunction (const char *name,
- lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
- lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
- m_name (name),
- m_local_addr (local_addr),
- m_remote_addr (remote_addr)
- {
- }
- };
-
ClangExpression &m_expr; ///< The expression to be parsed
std::auto_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into
@@ -188,8 +139,8 @@ private:
std::auto_ptr<clang::Builtin::Context> m_builtin_context; ///< Context for Clang built-ins
std::auto_ptr<clang::SelectorTable> m_selector_table; ///< Selector table for Objective-C methods
std::auto_ptr<clang::ASTContext> m_ast_context; ///< The AST context used to hold types and names for the parser
- std::auto_ptr<clang::CodeGenerator> m_code_generator; ///< [owned by the Execution Engine] The Clang object that generates IR
- std::vector<JittedFunction> m_jitted_functions; ///< A vector of all functions that have been JITted into machine code (just one, if ParseExpression() was called)
+ std::auto_ptr<clang::CodeGenerator> m_code_generator; ///< The Clang object that generates IR
+ std::auto_ptr<IRExecutionUnit> m_execution_unit; ///< The container for the finished Module
};
}
diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h
index b7484fa41a4..aae149552cc 100644
--- a/lldb/include/lldb/Expression/ClangUserExpression.h
+++ b/lldb/include/lldb/Expression/ClangUserExpression.h
@@ -26,7 +26,6 @@
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/IRForTarget.h"
-#include "lldb/Expression/ProcessDataAllocator.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/ExecutionContext.h"
@@ -433,7 +432,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<ProcessDataAllocator> m_data_allocator; ///< The allocator that the parser uses to place strings for use by JIT-compiled code.
std::auto_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed.
diff --git a/lldb/include/lldb/Expression/ClangUtilityFunction.h b/lldb/include/lldb/Expression/ClangUtilityFunction.h
index 14275c1c931..929f9238714 100644
--- a/lldb/include/lldb/Expression/ClangUtilityFunction.h
+++ b/lldb/include/lldb/Expression/ClangUtilityFunction.h
@@ -24,7 +24,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ProcessDataAllocator.h"
namespace lldb_private
{
@@ -170,7 +169,6 @@ public:
private:
std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
- std::auto_ptr<ProcessDataAllocator> m_data_allocator; ///< The allocator for static data used in the expression.
std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
std::string m_function_name; ///< The name of the function.
diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h
new file mode 100644
index 00000000000..4ff71ff5f00
--- /dev/null
+++ b/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -0,0 +1,512 @@
+//===-- IRExecutionUnit.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_IRExecutionUnit_h_
+#define lldb_IRExecutionUnit_h_
+
+// C Includes
+// C++ Includes
+#include <atomic>
+#include <string>
+#include <vector>
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Host/Mutex.h"
+
+namespace llvm {
+
+class Module;
+class ExecutionEngine;
+
+}
+
+namespace lldb_private {
+
+class Error;
+
+//----------------------------------------------------------------------
+/// @class IRExecutionUnit IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
+/// @brief Contains the IR and, optionally, JIT-compiled code for a module.
+///
+/// This class encapsulates the compiled version of an expression, in IR
+/// form (for interpretation purposes) and in raw machine code form (for
+/// execution in the target).
+///
+/// This object wraps an IR module that comes from the expression parser,
+/// and knows how to use the JIT to make it into executable code. It can
+/// then be used as input to the IR interpreter, or the address of the
+/// executable code can be passed to a thread plan to run in the target.
+///
+/// This class creates a subclass of LLVM's JITMemoryManager, because that is
+/// how the JIT emits code. Because LLDB needs to move JIT-compiled code
+/// into the target process, the IRExecutionUnit knows how to copy the
+/// emitted code into the target process.
+//----------------------------------------------------------------------
+class IRExecutionUnit
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ //------------------------------------------------------------------
+ IRExecutionUnit (std::auto_ptr<llvm::Module> &module_ap,
+ ConstString &name,
+ lldb::ProcessSP process_sp,
+ std::vector<std::string> &cpu_features);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~IRExecutionUnit();
+
+ llvm::Module *GetModule()
+ {
+ return m_module;
+ }
+
+ void GetRunnableInfo(Error &error,
+ lldb::addr_t &func_addr,
+ lldb::addr_t &func_end);
+
+ //------------------------------------------------------------------
+ /// Accessors for IRForTarget and other clients that may want binary
+ /// data placed on their behalf. The binary data is owned by the
+ /// IRExecutionUnit unless the client explicitly chooses to free it.
+ //------------------------------------------------------------------
+
+ lldb::addr_t WriteNow(const uint8_t *bytes,
+ size_t size,
+ Error &error);
+
+ void FreeNow(lldb::addr_t allocation);
+
+private:
+ //------------------------------------------------------------------
+ /// Look up the object in m_address_map that contains a given address,
+ /// find where it was copied to, and return the remote address at the
+ /// same offset into the copied entity
+ ///
+ /// @param[in] local_address
+ /// The address in the debugger.
+ ///
+ /// @return
+ /// The address in the target process.
+ //------------------------------------------------------------------
+ lldb::addr_t
+ GetRemoteAddressForLocal (lldb::addr_t local_address);
+
+ //------------------------------------------------------------------
+ /// Look up the object in m_address_map that contains a given address,
+ /// find where it was copied to, and return its address range in the
+ /// target process
+ ///
+ /// @param[in] local_address
+ /// The address in the debugger.
+ ///
+ /// @return
+ /// The range of the containing object in the target process.
+ //------------------------------------------------------------------
+ typedef std::pair <lldb::addr_t, uintptr_t> AddrRange;
+ AddrRange
+ GetRemoteRangeForLocal (lldb::addr_t local_address);
+
+ //------------------------------------------------------------------
+ /// Commit all allocations to the process and record where they were stored.
+ ///
+ /// @param[in] process
+ /// The process to allocate memory in.
+ ///
+ /// @return
+ /// True <=> all allocations were performed successfully.
+ /// This method will attempt to free allocated memory if the
+ /// operation fails.
+ //------------------------------------------------------------------
+ bool
+ CommitAllocations (lldb::ProcessSP &process_sp);
+
+ //------------------------------------------------------------------
+ /// Report all committed allocations to the execution engine.
+ ///
+ /// @param[in] engine
+ /// The execution engine to notify.
+ //------------------------------------------------------------------
+ void
+ ReportAllocations (llvm::ExecutionEngine &engine);
+
+ //------------------------------------------------------------------
+ /// Write the contents of all allocations to the process.
+ ///
+ /// @param[in] local_address
+ /// The process containing the allocations.
+ ///
+ /// @return
+ /// True <=> all allocations were performed successfully.
+ //------------------------------------------------------------------
+ bool
+ WriteData (lldb::ProcessSP &process_sp);
+
+ Error
+ DisassembleFunction (Stream &stream,
+ lldb::ProcessSP &process_sp);
+
+ class MemoryManager : public llvm::JITMemoryManager
+ {
+ public:
+ MemoryManager (IRExecutionUnit &parent);
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void setMemoryWritable ();
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void setMemoryExecutable ();
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void setPoisonMemory (bool poison)
+ {
+ m_default_mm_ap->setPoisonMemory (poison);
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void AllocateGOT()
+ {
+ m_default_mm_ap->AllocateGOT();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual uint8_t *getGOTBase() const
+ {
+ return m_default_mm_ap->getGOTBase();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual uint8_t *startFunctionBody(const llvm::Function *F,
+ uintptr_t &ActualSize);
+
+ //------------------------------------------------------------------
+ /// Allocate room for a dyld stub for a lazy-referenced function,
+ /// and add it to the m_stubs map
+ ///
+ /// @param[in] F
+ /// The function being referenced.
+ ///
+ /// @param[in] StubSize
+ /// The size of the stub.
+ ///
+ /// @param[in] Alignment
+ /// The required alignment of the stub.
+ ///
+ /// @return
+ /// Allocated space for the stub.
+ //------------------------------------------------------------------
+ virtual uint8_t *allocateStub(const llvm::GlobalValue* F,
+ unsigned StubSize,
+ unsigned Alignment);
+
+ //------------------------------------------------------------------
+ /// Complete the body of a function, and add it to the m_functions map
+ ///
+ /// @param[in] F
+ /// The function being completed.
+ ///
+ /// @param[in] FunctionStart
+ /// The first instruction of the function.
+ ///
+ /// @param[in] FunctionEnd
+ /// The last byte of the last instruction of the function.
+ //------------------------------------------------------------------
+ virtual void endFunctionBody(const llvm::Function *F,
+ uint8_t *FunctionStart,
+ uint8_t *FunctionEnd);
+ //------------------------------------------------------------------
+ /// Allocate space for an unspecified purpose, and add it to the
+ /// m_spaceBlocks map
+ ///
+ /// @param[in] Size
+ /// The size of the area.
+ ///
+ /// @param[in] Alignment
+ /// The required alignment of the area.
+ ///
+ /// @return
+ /// Allocated space.
+ //------------------------------------------------------------------
+ virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
+
+ //------------------------------------------------------------------
+ /// Allocate space for executable code, and add it to the
+ /// m_spaceBlocks map
+ ///
+ /// @param[in] Size
+ /// The size of the area.
+ ///
+ /// @param[in] Alignment
+ /// The required alignment of the area.
+ ///
+ /// @param[in] SectionID
+ /// A unique identifier for the section.
+ ///
+ /// @return
+ /// Allocated space.
+ //------------------------------------------------------------------
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID);
+
+ //------------------------------------------------------------------
+ /// Allocate space for data, and add it to the m_spaceBlocks map
+ ///
+ /// @param[in] Size
+ /// The size of the area.
+ ///
+ /// @param[in] Alignment
+ /// The required alignment of the area.
+ ///
+ /// @param[in] SectionID
+ /// A unique identifier for the section.
+ ///
+ /// @param[in] IsReadOnly
+ /// Flag indicating the section is read-only.
+ ///
+ /// @return
+ /// Allocated space.
+ //------------------------------------------------------------------
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, bool IsReadOnly);
+
+ //------------------------------------------------------------------
+ /// Allocate space for a global variable, and add it to the
+ /// m_spaceBlocks map
+ ///
+ /// @param[in] Size
+ /// The size of the variable.
+ ///
+ /// @param[in] Alignment
+ /// The required alignment of the variable.
+ ///
+ /// @return
+ /// Allocated space for the global.
+ //------------------------------------------------------------------
+ virtual uint8_t *allocateGlobal(uintptr_t Size,
+ unsigned Alignment);
+
+ //------------------------------------------------------------------
+ /// Called when object loading is complete and section page
+ /// permissions can be applied. Currently unimplemented for LLDB.
+ ///
+ /// @param[out] ErrMsg
+ /// The error that prevented the page protection from succeeding.
+ ///
+ /// @return
+ /// True in case of failure, false in case of success.
+ //------------------------------------------------------------------
+ bool applyPermissions(std::string *ErrMsg) { return false; }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void deallocateFunctionBody(void *Body);
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual uint8_t* startExceptionTable(const llvm::Function* F,
+ uintptr_t &ActualSize);
+
+ //------------------------------------------------------------------
+ /// Complete the exception table for a function, and add it to the
+ /// m_exception_tables map
+ ///
+ /// @param[in] F
+ /// The function whose exception table is being written.
+ ///
+ /// @param[in] TableStart
+ /// The first byte of the exception table.
+ ///
+ /// @param[in] TableEnd
+ /// The last byte of the exception table.
+ ///
+ /// @param[in] FrameRegister
+ /// I don't know what this does, but it's passed through.
+ //------------------------------------------------------------------
+ virtual void endExceptionTable(const llvm::Function *F,
+ uint8_t *TableStart,
+ uint8_t *TableEnd,
+ uint8_t* FrameRegister);
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void deallocateExceptionTable(void *ET);
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual size_t GetDefaultCodeSlabSize() {
+ return m_default_mm_ap->GetDefaultCodeSlabSize();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual size_t GetDefaultDataSlabSize() {
+ return m_default_mm_ap->GetDefaultDataSlabSize();
+ }
+
+ virtual size_t GetDefaultStubSlabSize() {
+ return m_default_mm_ap->GetDefaultStubSlabSize();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual unsigned GetNumCodeSlabs() {
+ return m_default_mm_ap->GetNumCodeSlabs();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual unsigned GetNumDataSlabs() {
+ return m_default_mm_ap->GetNumDataSlabs();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual unsigned GetNumStubSlabs() {
+ return m_default_mm_ap->GetNumStubSlabs();
+ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+ //------------------------------------------------------------------
+ virtual void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure = true) {
+ return m_default_mm_ap->getPointerToNamedFunction(Name, AbortOnFailure);
+ }
+ private:
+ std::auto_ptr<JITMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it.
+ IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for.
+ };
+
+ //----------------------------------------------------------------------
+ /// @class Allocation IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
+ /// @brief A record of a region that has been allocated by the JIT.
+ ///
+ /// The IRExecutionUnit makes records of all regions that need copying;
+ /// upon requests, it allocates and
+ //----------------------------------------------------------------------
+ struct Allocation
+ {
+ lldb::addr_t m_remote_allocation;///< The (unaligned) base for the remote allocation
+ lldb::addr_t m_remote_start; ///< The base address of the remote allocation
+ uintptr_t m_local_start; ///< The base address of the local allocation - LLDB_INVALID_ADDRESS means it was allocated with WriteNow
+ uintptr_t m_size; ///< The size of the allocation
+ unsigned m_section_id; ///< The ID of the section
+ unsigned m_alignment; ///< The required alignment for the allocation
+ bool m_executable; ///< True <=> the allocation must be executable in the target
+ bool m_allocated; ///< True <=> the allocation has been propagated to the target
+
+ static const unsigned eSectionIDNone = (unsigned)-1;
+
+ //------------------------------------------------------------------
+ /// Constructor
+ //------------------------------------------------------------------
+ Allocation () :
+ m_remote_allocation(0),
+ m_remote_start(0),
+ m_local_start(0),
+ m_size(0),
+ m_section_id(eSectionIDNone),
+ m_alignment(0),
+ m_executable(false),
+ m_allocated(false)
+ {
+ }
+
+ void dump (lldb::LogSP log);
+ };
+
+ //----------------------------------------------------------------------
+ /// @class JittedFunction ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
+ /// @brief Encapsulates a single function that has been generated by the JIT.
+ ///
+ /// Functions that have been generated by the JIT are first resident in the
+ /// local process, and then placed in the target process. JittedFunction
+ /// represents a function possibly resident in both.
+ //----------------------------------------------------------------------
+ struct JittedFunction {
+ std::string m_name; ///< The function's name
+ lldb::addr_t m_local_addr; ///< The address of the function in LLDB's memory
+ lldb::addr_t m_remote_addr; ///< The address of the function in the target's memory
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variabes.
+ ///
+ /// @param[in] name
+ /// The name of the function.
+ ///
+ /// @param[in] local_addr
+ /// The address of the function in LLDB, or LLDB_INVALID_ADDRESS if
+ /// it is not present in LLDB's memory.
+ ///
+ /// @param[in] remote_addr
+ /// The address of the function in the target, or LLDB_INVALID_ADDRESS
+ /// if it is not present in the target's memory.
+ //------------------------------------------------------------------
+ JittedFunction (const char *name,
+ lldb::addr_t local_addr = LLDB_INVALID_ADDRESS,
+ lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) :
+ m_name (name),
+ m_local_addr (local_addr),
+ m_remote_addr (remote_addr)
+ {
+ }
+ };
+
+ lldb::ProcessWP m_process_wp;
+ typedef std::vector<Allocation> AllocationList;
+ AllocationList m_allocations; ///< The base address of the remote allocation
+ std::auto_ptr<llvm::ExecutionEngine> m_execution_engine_ap;
+ std::auto_ptr<llvm::Module> m_module_ap; ///< Holder for the module until it's been handed off
+ llvm::Module *m_module; ///< Owned by the execution engine
+ std::vector<std::string> m_cpu_features;
+ llvm::SmallVector<JittedFunction, 1> m_jitted_functions; ///< A vector of all functions that have been JITted into machine code
+ const ConstString m_name;
+
+ std::atomic<bool> m_did_jit;
+ Mutex m_jit_mutex;
+
+ lldb::addr_t m_function_load_addr;
+ lldb::addr_t m_function_end_load_addr;
+};
+
+} // namespace lldb_private
+
+#endif // lldb_IRExecutionUnit_h_
diff --git a/lldb/include/lldb/Expression/IRForTarget.h b/lldb/include/lldb/Expression/IRForTarget.h
index 61c8deac5e0..b0a9aa8ad24 100644
--- a/lldb/include/lldb/Expression/IRForTarget.h
+++ b/lldb/include/lldb/Expression/IRForTarget.h
@@ -14,6 +14,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "llvm/Pass.h"
@@ -35,6 +36,7 @@ namespace llvm {
namespace lldb_private {
class ClangExpressionDeclMap;
+ class IRExecutionUnit;
}
//----------------------------------------------------------------------
@@ -54,14 +56,6 @@ namespace lldb_private {
class IRForTarget : public llvm::ModulePass
{
public:
- class StaticDataAllocator {
- public:
- StaticDataAllocator();
- virtual ~StaticDataAllocator();
- virtual lldb_private::StreamString &GetStream() = 0;
- virtual lldb::addr_t Allocate() = 0;
- };
-
//------------------------------------------------------------------
/// Constructor
///
@@ -84,8 +78,8 @@ public:
/// of the function, if it has no side-effects and the result can
/// be computed statically.
///
- /// @param[in] data_allocator
- /// If non-NULL, the static data allocator to use for literal strings.
+ /// @param[in] execution_unit
+ /// The holder for raw data associated with the expression.
///
/// @param[in] error_stream
/// If non-NULL, a stream on which errors can be printed.
@@ -97,7 +91,7 @@ public:
bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
- StaticDataAllocator *data_allocator,
+ lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream *error_stream,
const char* func_name = "$__lldb_expr");
@@ -653,6 +647,20 @@ private:
bool
StripAllGVs (llvm::Module &llvm_module);
+ class StaticDataAllocator {
+ public:
+ StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit);
+ lldb_private::StreamString &GetStream()
+ {
+ return m_stream_string;
+ }
+ lldb::addr_t Allocate();
+ private:
+ lldb_private::IRExecutionUnit &m_execution_unit;
+ lldb_private::StreamString m_stream_string;
+ lldb::addr_t m_allocation;
+ };
+
/// 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
@@ -663,7 +671,7 @@ private:
llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet.
std::auto_ptr<llvm::DataLayout> m_target_data; ///< The target data for the module being processed, or NULL if there is no module.
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; ///< The allocator to use for constant strings
llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type
lldb::ClangExpressionVariableSP &m_const_result; ///< This value should be set to the return value of the expression if it is constant and the expression has no side effects
diff --git a/lldb/include/lldb/Expression/ProcessDataAllocator.h b/lldb/include/lldb/Expression/ProcessDataAllocator.h
deleted file mode 100644
index 56ed22404db..00000000000
--- a/lldb/include/lldb/Expression/ProcessDataAllocator.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//===-- ProcessDataAllocator.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_ProcessDataAllocator_h_
-#define liblldb_ProcessDataAllocator_h_
-
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private.h"
-#include "lldb/Expression/IRForTarget.h"
-#include "lldb/Target/Process.h"
-
-namespace lldb_private
-{
-
-class ProcessDataAllocator : public IRForTarget::StaticDataAllocator {
-public:
- ProcessDataAllocator(Process &process) :
- IRForTarget::StaticDataAllocator(),
- m_process(process),
- m_stream_string(StreamString::eBinary, process.GetAddressByteSize(), process.GetByteOrder()),
- m_allocation(0)
- {
- }
-
- ~ProcessDataAllocator()
- {
- if (m_allocation)
- m_process.DeallocateMemory(m_allocation);
- }
-
- lldb_private::StreamString &GetStream()
- {
- return m_stream_string;
- }
-
- lldb::addr_t Allocate()
- {
- Error err;
-
- if (m_allocation)
- m_process.DeallocateMemory(m_allocation);
-
- m_allocation = m_process.AllocateMemory(m_stream_string.GetSize(), lldb::ePermissionsReadable | lldb::ePermissionsWritable, err);
-
- if (!err.Success())
- return 0;
-
- if (m_allocation)
- m_process.WriteMemory(m_allocation, m_stream_string.GetData(), m_stream_string.GetSize(), err);
-
- if (!err.Success())
- return 0;
-
- return m_allocation;
- }
-
- void Dump(lldb_private::Stream &stream);
-private:
- Process &m_process;
- StreamString m_stream_string;
- lldb::addr_t m_allocation;
-};
-
-} // namespace lldb_private
-
-#endif
diff --git a/lldb/include/lldb/Expression/RecordingMemoryManager.h b/lldb/include/lldb/Expression/RecordingMemoryManager.h
deleted file mode 100644
index b9758e17614..00000000000
--- a/lldb/include/lldb/Expression/RecordingMemoryManager.h
+++ /dev/null
@@ -1,424 +0,0 @@
-//===-- RecordingMemoryManager.h --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_RecordingMemoryManager_h_
-#define lldb_RecordingMemoryManager_h_
-
-// C Includes
-// C++ Includes
-#include <string>
-#include <vector>
-#include <map>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Core/Log.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionParser.h"
-
-namespace lldb_private {
-
-//----------------------------------------------------------------------
-/// @class RecordingMemoryManager RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h"
-/// @brief Passthrough memory manager for the JIT that records what was allocated where
-///
-/// The LLVM JIT is built to compile code for execution in the current
-/// process, so it needs to be able to allocate memory. Because different
-/// clients have different requirements for the locations of JIT compiled
-/// code, the interface for allocating memory has been abstracted out and
-/// can be implemented by any client.
-///
-/// LLDB, however, needs to move JIT-compiled code into the target process.
-/// Because writing individual bytes of code hasn't been abstracted out of
-/// the JIT, LLDB instead implements a custom memory allocator that records
-/// what regions have been allocated for code. When JIT compilation is
-/// complete, these regions are then copied as necessary into the target
-/// process.
-///
-/// Ideally the memory manager would handle this copying, but this class has
-/// to be built without RTTI, which means it cannot include Process.h. As a
-/// result, ClangExpression::WriteJITCode() accesses the stored mappings
-/// directly.
-//----------------------------------------------------------------------
-class RecordingMemoryManager : public llvm::JITMemoryManager
-{
-public:
- //------------------------------------------------------------------
- /// Constructor
- //------------------------------------------------------------------
- RecordingMemoryManager ();
-
- //------------------------------------------------------------------
- /// Destructor
- //------------------------------------------------------------------
- virtual ~RecordingMemoryManager();
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void setMemoryWritable ();
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void setMemoryExecutable ();
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void setPoisonMemory (bool poison)
- {
- m_default_mm_ap->setPoisonMemory (poison);
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void AllocateGOT()
- {
- m_default_mm_ap->AllocateGOT();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual uint8_t *getGOTBase() const
- {
- return m_default_mm_ap->getGOTBase();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual uint8_t *startFunctionBody(const llvm::Function *F,
- uintptr_t &ActualSize);
-
- //------------------------------------------------------------------
- /// Allocate room for a dyld stub for a lazy-referenced function,
- /// and add it to the m_stubs map
- ///
- /// @param[in] F
- /// The function being referenced.
- ///
- /// @param[in] StubSize
- /// The size of the stub.
- ///
- /// @param[in] Alignment
- /// The required alignment of the stub.
- ///
- /// @return
- /// Allocated space for the stub.
- //------------------------------------------------------------------
- virtual uint8_t *allocateStub(const llvm::GlobalValue* F,
- unsigned StubSize,
- unsigned Alignment);
-
- //------------------------------------------------------------------
- /// Complete the body of a function, and add it to the m_functions map
- ///
- /// @param[in] F
- /// The function being completed.
- ///
- /// @param[in] FunctionStart
- /// The first instruction of the function.
- ///
- /// @param[in] FunctionEnd
- /// The last byte of the last instruction of the function.
- //------------------------------------------------------------------
- virtual void endFunctionBody(const llvm::Function *F,
- uint8_t *FunctionStart,
- uint8_t *FunctionEnd);
- //------------------------------------------------------------------
- /// Allocate space for an unspecified purpose, and add it to the
- /// m_spaceBlocks map
- ///
- /// @param[in] Size
- /// The size of the area.
- ///
- /// @param[in] Alignment
- /// The required alignment of the area.
- ///
- /// @return
- /// Allocated space.
- //------------------------------------------------------------------
- virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
-
- //------------------------------------------------------------------
- /// Allocate space for executable code, and add it to the
- /// m_spaceBlocks map
- ///
- /// @param[in] Size
- /// The size of the area.
- ///
- /// @param[in] Alignment
- /// The required alignment of the area.
- ///
- /// @param[in] SectionID
- /// A unique identifier for the section.
- ///
- /// @return
- /// Allocated space.
- //------------------------------------------------------------------
- virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID);
-
- //------------------------------------------------------------------
- /// Allocate space for data, and add it to the m_spaceBlocks map
- ///
- /// @param[in] Size
- /// The size of the area.
- ///
- /// @param[in] Alignment
- /// The required alignment of the area.
- ///
- /// @param[in] SectionID
- /// A unique identifier for the section.
- ///
- /// @param[in] IsReadOnly
- /// Flag indicating the section is read-only.
- ///
- /// @return
- /// Allocated space.
- //------------------------------------------------------------------
- virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, bool IsReadOnly);
-
- //------------------------------------------------------------------
- /// Allocate space for a global variable, and add it to the
- /// m_spaceBlocks map
- ///
- /// @param[in] Size
- /// The size of the variable.
- ///
- /// @param[in] Alignment
- /// The required alignment of the variable.
- ///
- /// @return
- /// Allocated space for the global.
- //------------------------------------------------------------------
- virtual uint8_t *allocateGlobal(uintptr_t Size,
- unsigned Alignment);
-
- //------------------------------------------------------------------
- /// Called when object loading is complete and section page
- /// permissions can be applied. Currently unimplemented for LLDB.
- ///
- /// @param[out] ErrMsg
- /// The error that prevented the page protection from succeeding.
- ///
- /// @return
- /// True in case of failure, false in case of success.
- //------------------------------------------------------------------
- bool applyPermissions(std::string *ErrMsg) { return false; }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void deallocateFunctionBody(void *Body);
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual uint8_t* startExceptionTable(const llvm::Function* F,
- uintptr_t &ActualSize);
-
- //------------------------------------------------------------------
- /// Complete the exception table for a function, and add it to the
- /// m_exception_tables map
- ///
- /// @param[in] F
- /// The function whose exception table is being written.
- ///
- /// @param[in] TableStart
- /// The first byte of the exception table.
- ///
- /// @param[in] TableEnd
- /// The last byte of the exception table.
- ///
- /// @param[in] FrameRegister
- /// I don't know what this does, but it's passed through.
- //------------------------------------------------------------------
- virtual void endExceptionTable(const llvm::Function *F,
- uint8_t *TableStart,
- uint8_t *TableEnd,
- uint8_t* FrameRegister);
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void deallocateExceptionTable(void *ET);
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual size_t GetDefaultCodeSlabSize() {
- return m_default_mm_ap->GetDefaultCodeSlabSize();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual size_t GetDefaultDataSlabSize() {
- return m_default_mm_ap->GetDefaultDataSlabSize();
- }
-
- virtual size_t GetDefaultStubSlabSize() {
- return m_default_mm_ap->GetDefaultStubSlabSize();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual unsigned GetNumCodeSlabs() {
- return m_default_mm_ap->GetNumCodeSlabs();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual unsigned GetNumDataSlabs() {
- return m_default_mm_ap->GetNumDataSlabs();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual unsigned GetNumStubSlabs() {
- return m_default_mm_ap->GetNumStubSlabs();
- }
-
- //------------------------------------------------------------------
- /// Passthrough interface stub
- //------------------------------------------------------------------
- virtual void *getPointerToNamedFunction(const std::string &Name,
- bool AbortOnFailure = true) {
- return m_default_mm_ap->getPointerToNamedFunction(Name, AbortOnFailure);
- }
-
- //------------------------------------------------------------------
- /// [Convenience method for ClangExpressionParser] Look up the object in
- /// m_address_map that contains a given address, find where it was
- /// copied to, and return the remote address at the same offset into
- /// the copied entity
- ///
- /// @param[in] local_address
- /// The address in the debugger.
- ///
- /// @return
- /// The address in the target process.
- //------------------------------------------------------------------
- lldb::addr_t
- GetRemoteAddressForLocal (lldb::addr_t local_address);
-
- //------------------------------------------------------------------
- /// [Convenience method for ClangExpressionParser] Look up the object in
- /// m_address_map that contains a given address, find where it was
- /// copied to, and return its address range in the target process
- ///
- /// @param[in] local_address
- /// The address in the debugger.
- ///
- /// @return
- /// The range of the containing object in the target process.
- //------------------------------------------------------------------
- typedef std::pair <lldb::addr_t, uintptr_t> AddrRange;
- AddrRange
- GetRemoteRangeForLocal (lldb::addr_t local_address);
-
- //------------------------------------------------------------------
- /// [Convenience method for ClangExpressionParser] Commit all allocations
- /// to the process and record where they were stored.
- ///
- /// @param[in] process
- /// The process to allocate memory in.
- ///
- /// @return
- /// True <=> all allocations were performed successfully.
- /// This method will attempt to free allocated memory if the
- /// operation fails.
- //------------------------------------------------------------------
- bool
- CommitAllocations (Process &process);
-
- //------------------------------------------------------------------
- /// [Convenience method for ClangExpressionParser] Report all committed
- /// allocations to the execution engine.
- ///
- /// @param[in] engine
- /// The execution engine to notify.
- //------------------------------------------------------------------
- void
- ReportAllocations (llvm::ExecutionEngine &engine);
-
- //------------------------------------------------------------------
- /// [Convenience method for ClangExpressionParser] Write the contents
- /// of all allocations to the process.
- ///
- /// @param[in] local_address
- /// The process containing the allocations.
- ///
- /// @return
- /// True <=> all allocations were performed successfully.
- //------------------------------------------------------------------
- bool
- WriteData (Process &process);
-private:
- std::auto_ptr<JITMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it.
-
- lldb::LogSP m_log; ///< The log to use when printing log messages. May be NULL.
-
- //----------------------------------------------------------------------
- /// @class Allocation RecordingMemoryManager.h "lldb/Expression/RecordingMemoryManager.h"
- /// @brief A record of a region that has been allocated by the JIT.
- ///
- /// The RecordingMemoryManager makes records of all regions that need copying;
- /// upon requests, it allocates and
- //----------------------------------------------------------------------
- struct Allocation
- {
- lldb::addr_t m_remote_allocation;///< The (unaligned) base for the remote allocation
- lldb::addr_t m_remote_start; ///< The base address of the remote allocation
- uintptr_t m_local_start; ///< The base address of the local allocation
- uintptr_t m_size; ///< The size of the allocation
- unsigned m_section_id; ///< The ID of the section
- unsigned m_alignment; ///< The required alignment for the allocation
- bool m_executable; ///< True <=> the allocation must be executable in the target
- bool m_allocated; ///< True <=> the allocation has been propagated to the target
-
- static const unsigned eSectionIDNone = (unsigned)-1;
-
- //------------------------------------------------------------------
- /// Constructor
- //------------------------------------------------------------------
- Allocation () :
- m_remote_allocation(0),
- m_remote_start(0),
- m_local_start(0),
- m_size(0),
- m_section_id(eSectionIDNone),
- m_alignment(0),
- m_executable(false),
- m_allocated(false)
- {
- }
-
- void dump (lldb::LogSP log);
- };
-
- typedef std::vector<Allocation> AllocationList;
- AllocationList m_allocations; ///< The base address of the remote allocation
-};
-
-} // namespace lldb_private
-
-#endif // lldb_RecordingMemoryManager_h_
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index faafd94f3a0..ec10307c6f9 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -255,7 +255,7 @@
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 */; };
- 2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */; };
+ 2689006D13353E0E00698AC0 /* IRExecutionUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */; };
2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; };
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FA43171301048600E71120 /* FileSpec.cpp */; };
2689007013353E1A00698AC0 /* Condition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1B1236C5D400C660B5 /* Condition.cpp */; };
@@ -495,7 +495,6 @@
49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */; };
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 */; };
49DA65031485C92A005FF180 /* AppleObjCTypeVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCTypeVendor.cpp */; };
4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66499F14EEE7F100B0316F /* StreamCallback.h */; };
@@ -1444,8 +1443,6 @@
49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTResultSynthesizer.h; path = include/lldb/Expression/ASTResultSynthesizer.h; sourceTree = "<group>"; };
49B01A2D15F67B1700666829 /* TypeVendor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeVendor.h; path = include/lldb/Symbol/TypeVendor.h; sourceTree = "<group>"; };
49BB309511F79450001A4197 /* TaggedASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaggedASTType.h; path = include/lldb/Symbol/TaggedASTType.h; sourceTree = "<group>"; };
- 49C850761384A02F007DB519 /* ProcessDataAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProcessDataAllocator.h; path = include/lldb/Expression/ProcessDataAllocator.h; sourceTree = "<group>"; };
- 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessDataAllocator.cpp; path = source/Expression/ProcessDataAllocator.cpp; sourceTree = "<group>"; };
49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRDynamicChecks.cpp; path = source/Expression/IRDynamicChecks.cpp; sourceTree = "<group>"; };
49CF9833122C718B007A0B96 /* IRDynamicChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRDynamicChecks.h; path = include/lldb/Expression/IRDynamicChecks.h; sourceTree = "<group>"; };
49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangPersistentVariables.h; path = include/lldb/Expression/ClangPersistentVariables.h; sourceTree = "<group>"; };
@@ -1484,9 +1481,9 @@
4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallUserExpression.h; path = include/lldb/Target/ThreadPlanCallUserExpression.h; sourceTree = "<group>"; };
4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallUserExpression.cpp; path = source/Target/ThreadPlanCallUserExpression.cpp; sourceTree = "<group>"; };
4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunction.cpp; path = source/Expression/ClangFunction.cpp; sourceTree = "<group>"; };
- 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecordingMemoryManager.cpp; path = source/Expression/RecordingMemoryManager.cpp; sourceTree = "<group>"; };
+ 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRExecutionUnit.cpp; path = source/Expression/IRExecutionUnit.cpp; sourceTree = "<group>"; };
4C98D3E0118FB98F00E575D0 /* ClangFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunction.h; path = include/lldb/Expression/ClangFunction.h; sourceTree = "<group>"; };
- 4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecordingMemoryManager.h; path = include/lldb/Expression/RecordingMemoryManager.h; sourceTree = "<group>"; };
+ 4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRExecutionUnit.h; path = include/lldb/Expression/IRExecutionUnit.h; sourceTree = "<group>"; };
4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectApropos.cpp; path = source/Commands/CommandObjectApropos.cpp; sourceTree = "<group>"; };
4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectApropos.h; path = source/Commands/CommandObjectApropos.h; sourceTree = "<group>"; };
4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileRegex.h; path = include/lldb/Breakpoint/BreakpointResolverFileRegex.h; sourceTree = "<group>"; };
@@ -2883,14 +2880,12 @@
491193501226386000578B7F /* ASTStructExtractor.cpp */,
49CF9833122C718B007A0B96 /* IRDynamicChecks.h */,
49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
+ 4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */,
+ 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */,
49307AB111DEA4F20081F992 /* IRForTarget.h */,
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */,
496B015A1406DEB100F830D5 /* IRInterpreter.h */,
496B01581406DE8900F830D5 /* IRInterpreter.cpp */,
- 4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */,
- 4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */,
- 49C850761384A02F007DB519 /* ProcessDataAllocator.h */,
- 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */,
);
name = Expression;
sourceTree = "<group>";
@@ -3938,7 +3933,6 @@
files = (
9456F2241616671900656F91 /* DynamicLibrary.cpp in Sources */,
26D1804216CEDF0700EDFB5B /* TimeSpecTimeout.cpp in Sources */,
- 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */,
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
2689FFDB13353DA300698AC0 /* lldb-log.cpp in Sources */,
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
@@ -4048,7 +4042,7 @@
2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */,
2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */,
2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */,
- 2689006D13353E0E00698AC0 /* RecordingMemoryManager.cpp in Sources */,
+ 2689006D13353E0E00698AC0 /* IRExecutionUnit.cpp in Sources */,
2689006E13353E1A00698AC0 /* File.cpp in Sources */,
94D6A0AB16CEB55F00833B6E /* NSDictionary.cpp in Sources */,
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */,
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 58ecd13822b..4f8e3341494 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -20,8 +20,8 @@
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -188,8 +188,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
ClangExpression &expr) :
m_expr (expr),
m_compiler (),
- m_code_generator (NULL),
- m_jitted_functions ()
+ m_code_generator (NULL)
{
// Initialize targets first, so that --version shows registered targets.
static struct InitializeLLVM {
@@ -441,7 +440,7 @@ ClangExpressionParser::Parse (Stream &stream)
return num_errors;
}
-static bool FindFunctionInModule (std::string &mangled_name,
+static bool FindFunctionInModule (ConstString &mangled_name,
llvm::Module *module,
const char *orig_name)
{
@@ -451,7 +450,7 @@ static bool FindFunctionInModule (std::string &mangled_name,
{
if (fi->getName().str().find(orig_name) != std::string::npos)
{
- mangled_name = fi->getName().str();
+ mangled_name.SetCString(fi->getName().str().c_str());
return true;
}
}
@@ -460,16 +459,13 @@ static bool FindFunctionInModule (std::string &mangled_name,
}
Error
-ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
- lldb::addr_t &func_addr,
+ClangExpressionParser::PrepareForExecution (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;
func_end = LLDB_INVALID_ADDRESS;
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -489,7 +485,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
// Find the actual name of the function (it's often mangled somehow)
- std::string function_name;
+ ConstString function_name;
if (!FindFunctionInModule(function_name, module_ap.get(), m_expr.FunctionName()))
{
@@ -500,9 +496,14 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
else
{
if (log)
- log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName());
+ log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
}
+ m_execution_unit.reset(new IRExecutionUnit(module_ap, // handed off here
+ function_name,
+ exe_ctx.GetProcessSP(),
+ m_compiler->getTargetOpts().Features));
+
ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
if (decl_map)
@@ -516,11 +517,11 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
m_expr.NeedsVariableResolution(),
execution_policy,
const_result,
- data_allocator,
+ *m_execution_unit,
error_stream,
- function_name.c_str());
+ function_name.AsCString());
- bool ir_can_run = ir_for_target.runOnModule(*module_ap);
+ bool ir_can_run = ir_for_target.runOnModule(*m_execution_unit->GetModule());
Error &interpreter_error(ir_for_target.getInterpreterError());
@@ -579,9 +580,9 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
}
- IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str());
+ IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
- if (!ir_dynamic_checks.runOnModule(*module_ap))
+ if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
{
err.SetErrorToGenericError();
err.SetErrorString("Couldn't add dynamic checks to the expression");
@@ -590,264 +591,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr,
}
}
- // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called
- // below so we don't need to free it.
- RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager();
-
- std::string error_string;
-
- if (log)
- {
- std::string s;
- raw_string_ostream oss(s);
-
- module_ap->print(oss, NULL);
-
- oss.flush();
-
- log->Printf ("Module being sent to JIT: \n%s", s.c_str());
- }
- llvm::Triple triple(module_ap->getTargetTriple());
- llvm::Function *function = module_ap->getFunction (function_name.c_str());
- llvm::Reloc::Model relocModel;
- llvm::CodeModel::Model codeModel;
- if (triple.isOSBinFormatELF())
- {
- relocModel = llvm::Reloc::Static;
- // This will be small for 32-bit and large for 64-bit.
- codeModel = llvm::CodeModel::JITDefault;
- }
- else
- {
- relocModel = llvm::Reloc::PIC_;
- codeModel = llvm::CodeModel::Small;
- }
- EngineBuilder builder(module_ap.release());
- builder.setEngineKind(EngineKind::JIT)
- .setErrorStr(&error_string)
- .setRelocationModel(relocModel)
- .setJITMemoryManager(jit_memory_manager)
- .setOptLevel(CodeGenOpt::Less)
- .setAllocateGVsWithCode(true)
- .setCodeModel(codeModel)
- .setUseMCJIT(true);
-
- StringRef mArch;
- StringRef mCPU;
- SmallVector<std::string, 0> mAttrs;
-
- for (std::string &feature : m_compiler->getTargetOpts().Features)
- mAttrs.push_back(feature);
-
- TargetMachine *target_machine = builder.selectTarget(triple,
- mArch,
- mCPU,
- mAttrs);
-
- execution_engine_ap.reset(builder.create(target_machine));
-
- if (!execution_engine_ap.get())
- {
- err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
- return err;
- }
-
- execution_engine_ap->DisableLazyCompilation();
-
-
- // We don't actually need the function pointer here, this just forces it to get resolved.
-
- void *fun_ptr = execution_engine_ap->getPointerToFunction(function);
+ m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
- // Errors usually cause failures in the JIT, but if we're lucky we get here.
-
- if (!function)
- {
- err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str());
- return err;
- }
-
- if (!fun_ptr)
- {
- err.SetErrorToGenericError();
- err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str());
- return err;
- }
-
- m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr));
-
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process == NULL)
- {
- err.SetErrorToGenericError();
- err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
- return err;
- }
-
- jit_memory_manager->CommitAllocations(*process);
- jit_memory_manager->ReportAllocations(*execution_engine_ap);
- jit_memory_manager->WriteData(*process);
-
- std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
- for (pos = m_jitted_functions.begin(); pos != end; pos++)
- {
- (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr);
-
- if (!(*pos).m_name.compare(function_name.c_str()))
- {
- RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr);
- func_end = func_range.first + func_range.second;
- func_addr = (*pos).m_remote_addr;
- }
- }
-
- if (log)
- {
- log->Printf("Code can be run in the target.");
-
- StreamString disassembly_stream;
-
- Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager);
-
- if (!err.Success())
- {
- log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
- }
- else
- {
- log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
- }
- }
-
- err.Clear();
return err;
}
-
-Error
-ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager)
-{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- const char *name = m_expr.FunctionName();
-
- Error ret;
-
- ret.Clear();
-
- lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
- lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-
- std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
- for (pos = m_jitted_functions.begin(); pos < end; pos++)
- {
- if (strstr(pos->m_name.c_str(), name))
- {
- func_local_addr = pos->m_local_addr;
- func_remote_addr = pos->m_remote_addr;
- }
- }
-
- if (func_local_addr == LLDB_INVALID_ADDRESS)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
- return ret;
- }
-
- if (log)
- log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-
- std::pair <lldb::addr_t, lldb::addr_t> func_range;
-
- func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr);
-
- if (func_range.first == 0 && func_range.second == 0)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
- return ret;
- }
-
- if (log)
- log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
-
- Target *target = exe_ctx.GetTargetPtr();
- if (!target)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the target");
- return ret;
- }
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
-
- Process *process = exe_ctx.GetProcessPtr();
- Error err;
- process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
-
- if (!err.Success())
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
- return ret;
- }
-
- ArchSpec arch(target->GetArchitecture());
-
- const char *plugin_name = NULL;
- const char *flavor_string = NULL;
- lldb::DisassemblerSP disassembler = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
-
- if (!disassembler)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
- return ret;
- }
-
- if (!process)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the process");
- return ret;
- }
-
- DataExtractor extractor(buffer_sp,
- process->GetByteOrder(),
- target->GetArchitecture().GetAddressByteSize());
-
- if (log)
- {
- log->Printf("Function data has contents:");
- extractor.PutToLog (log.get(),
- 0,
- extractor.GetByteSize(),
- func_remote_addr,
- 16,
- DataExtractor::TypeUInt8);
- }
-
- disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
-
- InstructionList &instruction_list = disassembler->GetInstructionList();
- const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
- for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
- instruction_index < num_instructions;
- ++instruction_index)
- {
- Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
- instruction->Dump (&stream,
- max_opcode_byte_size,
- true,
- true,
- &exe_ctx);
- stream.PutChar('\n');
- }
-
- return ret;
-}
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index 794e035287b..95b75574101 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -264,18 +264,17 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
bool evaluated_statically = false; // should stay that way
- Error jit_error (m_parser->PrepareForExecution (m_jit_alloc,
- m_jit_start_addr,
+ Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
exe_ctx,
- NULL,
evaluated_statically,
const_result,
eExecutionPolicyAlways));
if (!jit_error.Success())
return false;
- if (process && m_jit_alloc != LLDB_INVALID_ADDRESS)
+
+ if (process && m_jit_start_addr)
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
m_JITted = true;
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 5a1c3aa8b6e..98b5c63efd2 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -460,30 +460,17 @@ ClangUserExpression::Parse (Stream &error_stream,
//////////////////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically if possible
//
-
- if (execution_policy != eExecutionPolicyNever && process)
- m_data_allocator.reset(new ProcessDataAllocator(*process));
-
- Error jit_error = parser.PrepareForExecution (m_jit_alloc,
- m_jit_start_addr,
+
+ Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
exe_ctx,
- m_data_allocator.get(),
m_evaluated_statically,
m_const_result,
execution_policy);
-
- if (log && m_data_allocator.get())
- {
- StreamString dump_string;
- m_data_allocator->Dump(dump_string);
-
- log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
- }
if (jit_error.Success())
{
- if (process && m_jit_alloc != LLDB_INVALID_ADDRESS)
+ if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
return true;
}
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index 2f41ae9a2f3..e457bb94655 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -104,8 +104,6 @@ ClangUtilityFunction::Install (Stream &error_stream,
m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
- m_data_allocator.reset(new ProcessDataAllocator(*process));
-
if (!m_expr_decl_map->WillParse(exe_ctx))
{
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
@@ -133,23 +131,13 @@ ClangUtilityFunction::Install (Stream &error_stream,
bool evaluated_statically = false; // should stay that way
- Error jit_error = parser.PrepareForExecution (m_jit_alloc,
- m_jit_start_addr,
+ Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
m_jit_end_addr,
exe_ctx,
- m_data_allocator.get(),
evaluated_statically,
const_result,
eExecutionPolicyAlways);
- if (log)
- {
- StreamString dump_string;
- m_data_allocator->Dump(dump_string);
-
- log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
- }
-
if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
new file mode 100644
index 00000000000..c2a86d68654
--- /dev/null
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -0,0 +1,770 @@
+//===-- IRExecutionUnit.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/IR/Module.h"
+// Project includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+IRExecutionUnit::IRExecutionUnit (std::auto_ptr<llvm::Module> &module_ap,
+ ConstString &name,
+ lldb::ProcessSP process_sp,
+ std::vector<std::string> &cpu_features) :
+ m_process_wp(process_sp),
+ m_module_ap(module_ap),
+ m_module(m_module_ap.get()),
+ m_cpu_features(),
+ m_name(name),
+ m_did_jit(false),
+ m_function_load_addr(LLDB_INVALID_ADDRESS),
+ m_function_end_load_addr(LLDB_INVALID_ADDRESS)
+{
+ for (std::string &feature : cpu_features)
+ {
+ m_cpu_features.push_back(std::string(feature.c_str()));
+ }
+}
+
+lldb::addr_t
+IRExecutionUnit::WriteNow (const uint8_t *bytes,
+ size_t size,
+ Error &error)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Allocation allocation;
+ allocation.m_size = size;
+ allocation.m_alignment = 8;
+ allocation.m_local_start = LLDB_INVALID_ADDRESS;
+ allocation.m_section_id = Allocation::eSectionIDNone;
+
+ lldb_private::Error err;
+
+ size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
+
+ if (allocation_size == 0)
+ allocation_size = 1;
+
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (!process_sp)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't find the process");
+ }
+
+ allocation.m_remote_allocation = process_sp->AllocateMemory(allocation_size,
+ (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
+ err);
+
+ if (!err.Success())
+ return LLDB_INVALID_ADDRESS;
+
+ process_sp->WriteMemory(allocation.m_remote_allocation, bytes, size, err);
+
+ if (!err.Success())
+ {
+ process_sp->DeallocateMemory(allocation.m_remote_allocation);
+ allocation.m_remote_allocation = LLDB_INVALID_ADDRESS;
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ uint64_t mask = allocation.m_alignment - 1;
+
+ allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
+
+ allocation.m_allocated = true;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::WriteNow() wrote to 0x%llx", allocation.m_remote_start);
+ allocation.dump(log);
+ }
+
+ m_allocations.push_back(allocation);
+
+ return allocation.m_remote_start;
+}
+
+void
+IRExecutionUnit::FreeNow (lldb::addr_t allocation)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (allocation == LLDB_INVALID_ADDRESS)
+ return;
+
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+
+ if (!process_sp)
+ return;
+
+ for (auto ai = m_allocations.begin(), ae = m_allocations.end();
+ ai != ae;
+ ++ai)
+ {
+ if (ai->m_remote_allocation == allocation)
+ {
+ m_allocations.erase(ai);
+ log->Printf("IRExecutionUnit::FreeNow() freed 0x%llx", allocation);
+ return;
+ }
+ }
+}
+
+Error
+IRExecutionUnit::DisassembleFunction (Stream &stream,
+ lldb::ProcessSP &process_wp)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ ExecutionContext exe_ctx(process_wp);
+
+ Error ret;
+
+ ret.Clear();
+
+ lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
+
+ for (JittedFunction &function : m_jitted_functions)
+ {
+ if (strstr(function.m_name.c_str(), m_name.AsCString()))
+ {
+ func_local_addr = function.m_local_addr;
+ func_remote_addr = function.m_remote_addr;
+ }
+ }
+
+ if (func_local_addr == LLDB_INVALID_ADDRESS)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
+ return ret;
+ }
+
+ if (log)
+ log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
+
+ std::pair <lldb::addr_t, lldb::addr_t> func_range;
+
+ func_range = GetRemoteRangeForLocal(func_local_addr);
+
+ if (func_range.first == 0 && func_range.second == 0)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
+ return ret;
+ }
+
+ if (log)
+ log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the target");
+ return ret;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Error err;
+ process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
+
+ if (!err.Success())
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
+ return ret;
+ }
+
+ ArchSpec arch(target->GetArchitecture());
+
+ const char *plugin_name = NULL;
+ const char *flavor_string = NULL;
+ lldb::DisassemblerSP disassembler = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
+
+ if (!disassembler)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
+ return ret;
+ }
+
+ if (!process)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the process");
+ return ret;
+ }
+
+ DataExtractor extractor(buffer_sp,
+ process->GetByteOrder(),
+ target->GetArchitecture().GetAddressByteSize());
+
+ if (log)
+ {
+ log->Printf("Function data has contents:");
+ extractor.PutToLog (log.get(),
+ 0,
+ extractor.GetByteSize(),
+ func_remote_addr,
+ 16,
+ DataExtractor::TypeUInt8);
+ }
+
+ disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
+
+ InstructionList &instruction_list = disassembler->GetInstructionList();
+ const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
+
+ for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
+ instruction_index < num_instructions;
+ ++instruction_index)
+ {
+ Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
+ instruction->Dump (&stream,
+ max_opcode_byte_size,
+ true,
+ true,
+ &exe_ctx);
+ stream.PutChar('\n');
+ }
+
+ return ret;
+}
+
+void
+IRExecutionUnit::GetRunnableInfo(Error &error,
+ lldb::addr_t &func_addr,
+ lldb::addr_t &func_end)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb::ProcessSP process_sp(m_process_wp.lock());
+
+ func_addr = LLDB_INVALID_ADDRESS;
+ func_end = LLDB_INVALID_ADDRESS;
+
+ if (!process_sp)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
+ return;
+ }
+
+ if (m_did_jit)
+ {
+ func_addr = m_function_load_addr;
+ func_end = m_function_end_load_addr;
+
+ return;
+ }; // someone else may have gotten the mutex first
+
+ {
+ Mutex::Locker jit_mutex_locker(m_jit_mutex);
+
+ if (m_did_jit)
+ {
+ func_addr = m_function_load_addr;
+ func_end = m_function_end_load_addr;
+
+ return;
+ }; // someone else may have gotten the mutex first
+
+ m_did_jit = true;
+
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ std::string error_string;
+
+ if (log)
+ {
+ std::string s;
+ llvm::raw_string_ostream oss(s);
+
+ m_module->print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf ("Module being sent to JIT: \n%s", s.c_str());
+ }
+
+ llvm::Triple triple(m_module->getTargetTriple());
+ llvm::Function *function = m_module->getFunction (m_name.AsCString());
+ llvm::Reloc::Model relocModel;
+ llvm::CodeModel::Model codeModel;
+
+ if (triple.isOSBinFormatELF())
+ {
+ relocModel = llvm::Reloc::Static;
+ // This will be small for 32-bit and large for 64-bit.
+ codeModel = llvm::CodeModel::JITDefault;
+ }
+ else
+ {
+ relocModel = llvm::Reloc::PIC_;
+ codeModel = llvm::CodeModel::Small;
+ }
+
+ llvm::EngineBuilder builder(m_module_ap.get());
+
+ builder.setEngineKind(llvm::EngineKind::JIT)
+ .setErrorStr(&error_string)
+ .setRelocationModel(relocModel)
+ .setJITMemoryManager(new MemoryManager(*this))
+ .setOptLevel(llvm::CodeGenOpt::Less)
+ .setAllocateGVsWithCode(true)
+ .setCodeModel(codeModel)
+ .setUseMCJIT(true);
+
+ llvm::StringRef mArch;
+ llvm::StringRef mCPU;
+ llvm::SmallVector<std::string, 0> mAttrs;
+
+ for (std::string &feature : m_cpu_features)
+ mAttrs.push_back(feature);
+
+ llvm::TargetMachine *target_machine = builder.selectTarget(triple,
+ mArch,
+ mCPU,
+ mAttrs);
+
+ m_execution_engine_ap.reset(builder.create(target_machine));
+
+ if (!m_execution_engine_ap.get())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
+ return;
+ }
+ else
+ {
+ m_module_ap.release(); // ownership was transferred
+ }
+
+ m_execution_engine_ap->DisableLazyCompilation();
+
+ // We don't actually need the function pointer here, this just forces it to get resolved.
+
+ void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
+
+ // Errors usually cause failures in the JIT, but if we're lucky we get here.
+
+ if (!function)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
+ return;
+ }
+
+ if (!fun_ptr)
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
+ return;
+ }
+
+ m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
+
+ CommitAllocations(process_sp);
+ ReportAllocations(*m_execution_engine_ap);
+ WriteData(process_sp);
+
+ for (JittedFunction &jitted_function : m_jitted_functions)
+ {
+ jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
+
+ if (!jitted_function.m_name.compare(m_name.AsCString()))
+ {
+ AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
+ m_function_end_load_addr = func_range.first + func_range.second;
+ m_function_load_addr = jitted_function.m_remote_addr;
+ }
+ }
+
+ if (log)
+ {
+ log->Printf("Code can be run in the target.");
+
+ StreamString disassembly_stream;
+
+ Error err = DisassembleFunction(disassembly_stream, process_sp);
+
+ if (!err.Success())
+ {
+ log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
+ }
+ else
+ {
+ log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
+ }
+ }
+
+ func_addr = m_function_load_addr;
+ func_end = m_function_end_load_addr;
+
+ return;
+ }
+}
+
+IRExecutionUnit::~IRExecutionUnit ()
+{
+}
+
+IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
+ m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
+ m_parent (parent)
+{
+}
+
+void
+IRExecutionUnit::MemoryManager::setMemoryWritable ()
+{
+ m_default_mm_ap->setMemoryWritable();
+}
+
+void
+IRExecutionUnit::MemoryManager::setMemoryExecutable ()
+{
+ m_default_mm_ap->setMemoryExecutable();
+}
+
+
+uint8_t *
+IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F,
+ uintptr_t &ActualSize)
+{
+ return m_default_mm_ap->startFunctionBody(F, ActualSize);
+}
+
+uint8_t *
+IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
+ unsigned StubSize,
+ unsigned Alignment)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
+
+ Allocation allocation;
+ allocation.m_size = StubSize;
+ allocation.m_alignment = Alignment;
+ allocation.m_local_start = (uintptr_t)return_value;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
+ F, StubSize, Alignment, return_value);
+ allocation.dump(log);
+ }
+
+ m_parent.m_allocations.push_back(allocation);
+
+ return return_value;
+}
+
+void
+IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
+ uint8_t *FunctionStart,
+ uint8_t *FunctionEnd)
+{
+ m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
+}
+
+uint8_t *
+IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
+
+ Allocation allocation;
+ allocation.m_size = Size;
+ allocation.m_alignment = Alignment;
+ allocation.m_local_start = (uintptr_t)return_value;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
+ (uint64_t)Size, Alignment, return_value);
+ allocation.dump(log);
+ }
+
+ m_parent.m_allocations.push_back(allocation);
+
+ return return_value;
+}
+
+uint8_t *
+IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
+ unsigned Alignment,
+ unsigned SectionID)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
+
+ Allocation allocation;
+ allocation.m_size = Size;
+ allocation.m_alignment = Alignment;
+ allocation.m_local_start = (uintptr_t)return_value;
+ allocation.m_section_id = SectionID;
+ allocation.m_executable = true;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
+ (uint64_t)Size, Alignment, SectionID, return_value);
+ allocation.dump(log);
+ }
+
+ m_parent.m_allocations.push_back(allocation);
+
+ return return_value;
+}
+
+uint8_t *
+IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
+ unsigned Alignment,
+ unsigned SectionID,
+ bool IsReadOnly)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
+
+ Allocation allocation;
+ allocation.m_size = Size;
+ allocation.m_alignment = Alignment;
+ allocation.m_local_start = (uintptr_t)return_value;
+ allocation.m_section_id = SectionID;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
+ (uint64_t)Size, Alignment, SectionID, return_value);
+ allocation.dump(log);
+ }
+
+ m_parent.m_allocations.push_back(allocation);
+
+ return return_value;
+}
+
+uint8_t *
+IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
+ unsigned Alignment)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
+
+ Allocation allocation;
+ allocation.m_size = Size;
+ allocation.m_alignment = Alignment;
+ allocation.m_local_start = (uintptr_t)return_value;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
+ (uint64_t)Size, Alignment, return_value);
+ allocation.dump(log);
+ }
+
+ m_parent.m_allocations.push_back(allocation);
+
+ return return_value;
+}
+
+void
+IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body)
+{
+ m_default_mm_ap->deallocateFunctionBody(Body);
+}
+
+uint8_t*
+IRExecutionUnit::MemoryManager::startExceptionTable(const llvm::Function* F,
+ uintptr_t &ActualSize)
+{
+ return m_default_mm_ap->startExceptionTable(F, ActualSize);
+}
+
+void
+IRExecutionUnit::MemoryManager::endExceptionTable(const llvm::Function *F,
+ uint8_t *TableStart,
+ uint8_t *TableEnd,
+ uint8_t* FrameRegister)
+{
+ m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
+}
+
+void
+IRExecutionUnit::MemoryManager::deallocateExceptionTable(void *ET)
+{
+ m_default_mm_ap->deallocateExceptionTable (ET);
+}
+
+lldb::addr_t
+IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
+{
+ for (Allocation &allocation : m_allocations)
+ {
+ if (local_address >= allocation.m_local_start &&
+ local_address < allocation.m_local_start + allocation.m_size)
+ return allocation.m_remote_start + (local_address - allocation.m_local_start);
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+IRExecutionUnit::AddrRange
+IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
+{
+ for (Allocation &allocation : m_allocations)
+ {
+ if (local_address >= allocation.m_local_start &&
+ local_address < allocation.m_local_start + allocation.m_size)
+ return AddrRange(allocation.m_remote_start, allocation.m_size);
+ }
+
+ return AddrRange (0, 0);
+}
+
+bool
+IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ bool ret = true;
+
+ for (Allocation &allocation : m_allocations)
+ {
+ if (allocation.m_allocated)
+ continue;
+
+ lldb_private::Error err;
+
+ size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
+
+ if (allocation_size == 0)
+ allocation_size = 1;
+
+ allocation.m_remote_allocation = process_sp->AllocateMemory(
+ allocation_size,
+ allocation.m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
+ : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
+ err);
+
+ uint64_t mask = allocation.m_alignment - 1;
+
+ allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
+
+ if (!err.Success())
+ {
+ ret = false;
+ break;
+ }
+
+ allocation.m_allocated = true;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::CommitAllocations() committed an allocation");
+ allocation.dump(log);
+ }
+ }
+
+ if (!ret)
+ {
+ for (Allocation &allocation : m_allocations)
+ {
+ if (allocation.m_allocated)
+ process_sp->DeallocateMemory(allocation.m_remote_start);
+ }
+ }
+
+ return ret;
+}
+
+void
+IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
+{
+ for (Allocation &allocation : m_allocations)
+ {
+ if (!allocation.m_allocated)
+ continue;
+
+ if (allocation.m_local_start == LLDB_INVALID_ADDRESS)
+ continue;
+
+ engine.mapSectionAddress((void*)allocation.m_local_start, allocation.m_remote_start);
+ }
+ // Trigger re-application of relocations.
+ engine.finalizeObject();
+}
+
+bool
+IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ for (Allocation &allocation : m_allocations)
+ {
+ if (!allocation.m_allocated)
+ return false;
+
+ if (allocation.m_local_start == LLDB_INVALID_ADDRESS)
+ continue;
+
+ lldb_private::Error err;
+
+ if (process_sp->WriteMemory(allocation.m_remote_start,
+ (void*)allocation.m_local_start,
+ allocation.m_size,
+ err) != allocation.m_size ||
+ !err.Success())
+ return false;
+
+ if (log)
+ {
+ log->Printf("IRExecutionUnit::CommitAllocations() wrote an allocation");
+ allocation.dump(log);
+ }
+ }
+
+ return true;
+}
+
+void
+IRExecutionUnit::Allocation::dump (lldb::LogSP log)
+{
+ if (!log)
+ return;
+
+ log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
+ (unsigned long long)m_local_start,
+ (unsigned long long)m_size,
+ (unsigned long long)m_remote_start,
+ (unsigned)m_alignment,
+ (unsigned)m_section_id);
+}
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index c7c96f73fbd..279e034d832 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -22,12 +22,14 @@
#include "clang/AST/ASTContext.h"
-#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -38,19 +40,32 @@ using namespace llvm;
static char ID;
-IRForTarget::StaticDataAllocator::StaticDataAllocator()
+IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) :
+ m_execution_unit(execution_unit),
+ m_allocation(LLDB_INVALID_ADDRESS)
{
}
-IRForTarget::StaticDataAllocator::~StaticDataAllocator()
+lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
{
+ lldb_private::Error err;
+
+ if (m_allocation != LLDB_INVALID_ADDRESS)
+ {
+ m_execution_unit.FreeNow(m_allocation);
+ m_allocation = LLDB_INVALID_ADDRESS;
+ }
+
+ m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err);
+
+ return m_allocation;
}
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
lldb_private::ExecutionPolicy execution_policy,
lldb::ClangExpressionVariableSP &const_result,
- StaticDataAllocator *data_allocator,
+ lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
@@ -60,7 +75,7 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
m_func_name(func_name),
m_module(NULL),
m_decl_map(decl_map),
- m_data_allocator(data_allocator),
+ m_data_allocator(execution_unit),
m_CFStringCreateWithBytes(NULL),
m_sel_registerName(NULL),
m_const_result(const_result),
@@ -1559,7 +1574,7 @@ IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
if (global_variable == m_reloc_placeholder)
return true;
- uint64_t offset = m_data_allocator->GetStream().GetSize();
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
llvm::Type *variable_type = global_variable->getType();
@@ -1572,7 +1587,7 @@ IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator->GetStream().PutNHex8(aligned_offset - offset, 0);
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
offset = aligned_offset;
lldb_private::DataBufferHeap data(size, '\0');
@@ -1581,7 +1596,7 @@ IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
if (!MaterializeInitializer(data.GetBytes(), initializer))
return false;
- m_data_allocator->GetStream().Write(data.GetBytes(), data.GetByteSize());
+ m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize());
Constant *new_pointer = BuildRelocation(variable_type, offset);
@@ -1960,9 +1975,6 @@ IRForTarget::ReplaceStrings ()
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (!m_data_allocator)
- return true; // hope for the best; some clients may not want static allocation!
-
typedef std::map <GlobalVariable *, size_t> OffsetsTy;
OffsetsTy offsets;
@@ -2014,9 +2026,9 @@ IRForTarget::ReplaceStrings ()
str = gc_array->getAsString();
}
- offsets[gv] = m_data_allocator->GetStream().GetSize();
+ offsets[gv] = m_data_allocator.GetStream().GetSize();
- m_data_allocator->GetStream().Write(str.c_str(), str.length() + 1);
+ m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1);
}
Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
@@ -2083,9 +2095,6 @@ bool
IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_data_allocator)
- return true;
typedef SmallVector <Value*, 2> ConstantList;
typedef SmallVector <llvm::Instruction*, 2> UserList;
@@ -2156,7 +2165,7 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
lldb_private::DataBufferHeap data(operand_data_size, 0);
- if (lldb::endian::InlHostByteOrder() != m_data_allocator->GetStream().GetByteOrder())
+ if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
{
uint8_t *data_bytes = data.GetBytes();
@@ -2172,16 +2181,16 @@ IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
memcpy(data.GetBytes(), operand_raw_data, operand_data_size);
}
- uint64_t offset = m_data_allocator->GetStream().GetSize();
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
size_t align = m_target_data->getPrefTypeAlignment(operand_type);
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator->GetStream().PutNHex8(aligned_offset - offset, 0);
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
offset = aligned_offset;
- m_data_allocator->GetStream().Write(data.GetBytes(), operand_data_size);
+ m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size);
llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
@@ -2603,16 +2612,13 @@ 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())
+ if (!m_data_allocator.GetStream().GetSize())
return true;
- lldb::addr_t allocation = m_data_allocator->Allocate();
+ lldb::addr_t allocation = m_data_allocator.Allocate();
if (log)
{
@@ -2622,7 +2628,7 @@ IRForTarget::CompleteDataAllocation ()
log->Printf("Failed to allocate static data");
}
- if (!allocation)
+ if (!allocation || allocation == LLDB_INVALID_ADDRESS)
return false;
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
diff --git a/lldb/source/Expression/ProcessDataAllocator.cpp b/lldb/source/Expression/ProcessDataAllocator.cpp
deleted file mode 100644
index 3ac07708e91..00000000000
--- a/lldb/source/Expression/ProcessDataAllocator.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- ProcessDataAllocator.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/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Expression/ProcessDataAllocator.h"
-
-using namespace lldb_private;
-
-void
-ProcessDataAllocator::Dump(Stream &stream)
-{
- size_t data_size = m_stream_string.GetSize();
-
- if (!m_allocation)
- return;
-
- lldb::DataBufferSP data(new DataBufferHeap(data_size, 0));
-
- Error error;
- if (m_process.ReadMemory (m_allocation, data->GetBytes(), data_size, error) != data_size)
- return;
-
- DataExtractor extractor(data, m_process.GetByteOrder(), m_process.GetAddressByteSize());
-
- extractor.Dump(&stream, // stream
- 0, // offset
- lldb::eFormatBytesWithASCII, // format
- 1, // byte size of individual entries
- data_size, // number of entries
- 16, // entries per line
- m_allocation, // address to print
- 0, // bit size (bitfields only; 0 means ignore)
- 0); // bit alignment (bitfields only; 0 means ignore)
-
- stream.PutChar('\n');
-}
diff --git a/lldb/source/Expression/RecordingMemoryManager.cpp b/lldb/source/Expression/RecordingMemoryManager.cpp
deleted file mode 100644
index 2a81fc2d125..00000000000
--- a/lldb/source/Expression/RecordingMemoryManager.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-//===-- RecordingMemoryManager.cpp ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-// Project includes
-#include "lldb/Expression/RecordingMemoryManager.h"
-
-using namespace lldb_private;
-
-RecordingMemoryManager::RecordingMemoryManager () :
- llvm::JITMemoryManager(),
- m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
- m_log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
-{
-}
-
-RecordingMemoryManager::~RecordingMemoryManager ()
-{
-}
-
-void
-RecordingMemoryManager::setMemoryWritable ()
-{
- m_default_mm_ap->setMemoryWritable();
-}
-
-void
-RecordingMemoryManager::setMemoryExecutable ()
-{
- m_default_mm_ap->setMemoryExecutable();
-}
-
-
-uint8_t *
-RecordingMemoryManager::startFunctionBody(const llvm::Function *F,
- uintptr_t &ActualSize)
-{
- return m_default_mm_ap->startFunctionBody(F, ActualSize);
-}
-
-uint8_t *
-RecordingMemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
- unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
-
- Allocation allocation;
- allocation.m_size = StubSize;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
- F, StubSize, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-void
-RecordingMemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd)
-{
- m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
-}
-
-uint8_t *
-RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
- (uint64_t)Size, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID)
-{
- uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
- allocation.m_executable = true;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, bool IsReadOnly)
-{
- uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
- (uint64_t)Size, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-void
-RecordingMemoryManager::deallocateFunctionBody(void *Body)
-{
- m_default_mm_ap->deallocateFunctionBody(Body);
-}
-
-uint8_t*
-RecordingMemoryManager::startExceptionTable(const llvm::Function* F,
- uintptr_t &ActualSize)
-{
- return m_default_mm_ap->startExceptionTable(F, ActualSize);
-}
-
-void
-RecordingMemoryManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister)
-{
- m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
-}
-
-void
-RecordingMemoryManager::deallocateExceptionTable(void *ET)
-{
- m_default_mm_ap->deallocateExceptionTable (ET);
-}
-
-lldb::addr_t
-RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (local_address >= ai->m_local_start &&
- local_address < ai->m_local_start + ai->m_size)
- return ai->m_remote_start + (local_address - ai->m_local_start);
- }
-
- return LLDB_INVALID_ADDRESS;
-}
-
-RecordingMemoryManager::AddrRange
-RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (local_address >= ai->m_local_start &&
- local_address < ai->m_local_start + ai->m_size)
- return AddrRange(ai->m_remote_start, ai->m_size);
- }
-
- return AddrRange (0, 0);
-}
-
-bool
-RecordingMemoryManager::CommitAllocations (Process &process)
-{
- bool ret = true;
-
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (ai->m_allocated)
- continue;
-
- lldb_private::Error err;
-
- size_t allocation_size = (ai->m_size ? ai->m_size : 1) + ai->m_alignment - 1;
-
- if (allocation_size == 0)
- allocation_size = 1;
-
- ai->m_remote_allocation = process.AllocateMemory(
- allocation_size,
- ai->m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
- : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
- err);
-
- uint64_t mask = ai->m_alignment - 1;
-
- ai->m_remote_start = (ai->m_remote_allocation + mask) & (~mask);
-
- if (!err.Success())
- {
- ret = false;
- break;
- }
-
- ai->m_allocated = true;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation");
- ai->dump(m_log);
- }
- }
-
- if (!ret)
- {
- for (AllocationList::iterator ai = m_allocations.end(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (ai->m_allocated)
- process.DeallocateMemory(ai->m_remote_start);
- }
- }
-
- return ret;
-}
-
-void
-RecordingMemoryManager::ReportAllocations (llvm::ExecutionEngine &engine)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (!ai->m_allocated)
- continue;
-
- engine.mapSectionAddress((void*)ai->m_local_start, ai->m_remote_start);
- }
- // Trigger re-application of relocations.
- engine.finalizeObject();
-}
-
-bool
-RecordingMemoryManager::WriteData (Process &process)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (!ai->m_allocated)
- return false;
-
- lldb_private::Error err;
-
- if (process.WriteMemory(ai->m_remote_start,
- (void*)ai->m_local_start,
- ai->m_size,
- err) != ai->m_size ||
- !err.Success())
- return false;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation");
- ai->dump(m_log);
- }
- }
-
- return true;
-}
-
-void
-RecordingMemoryManager::Allocation::dump (lldb::LogSP log)
-{
- if (!log)
- return;
-
- log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
- (unsigned long long)m_local_start,
- (unsigned long long)m_size,
- (unsigned long long)m_remote_start,
- (unsigned)m_alignment,
- (unsigned)m_section_id);
-}
OpenPOWER on IntegriCloud