[Lldb-commits] [lldb] r178832 - Factored out memory access into the target process

Sean Callanan scallanan at apple.com
Thu Apr 4 19:22:57 PDT 2013


Author: spyffe
Date: Thu Apr  4 21:22:57 2013
New Revision: 178832

URL: http://llvm.org/viewvc/llvm-project?rev=178832&view=rev
Log:
Factored out memory access into the target process
from IRExecutionUnit into a superclass called
IRMemoryMap.  IRMemoryMap handles all reading and
writing, ensuring that areas are kept track of and
memory is properly cached (and deleted).

Also fixed several cases where we would simply leak
binary data in the target process over time.  Now
the expression objects explicitly own their
IRExecutionUnit and delete it when they go away.  This
is why I had to modify ClangUserExpression,
ClangUtilityFunction, and ClangFunction.

As a side effect of this, I am removing the JIT
mutex for an IRMemoryMap.  If it turns out that we
need this mutex, I'll add it in then, but right now
it's just adding complexity.

This is part of a more general project to make
expressions fully reusable.  The next step is to
make materialization and dematerialization use
the IRMemoryMap API rather than writing and
reading directly from the process's memory. 
This will allow the IR interpreter to use the
same data, but in the host's memory, without having
to use a different set of pointers.

Added:
    lldb/trunk/include/lldb/Expression/IRMemoryMap.h
    lldb/trunk/source/Expression/IRMemoryMap.cpp
Modified:
    lldb/trunk/include/lldb/Expression/ClangExpression.h
    lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
    lldb/trunk/include/lldb/Expression/ClangFunction.h
    lldb/trunk/include/lldb/Expression/ClangUserExpression.h
    lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h
    lldb/trunk/include/lldb/Expression/IRExecutionUnit.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Expression/ClangExpressionParser.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Expression/ClangUtilityFunction.cpp
    lldb/trunk/source/Expression/IRExecutionUnit.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpression.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpression.h Thu Apr  4 21:22:57 2013
@@ -93,13 +93,6 @@ public:
     DeclMap () = 0;
     
     //------------------------------------------------------------------
-    /// Return the object that the parser should use when registering
-    /// local variables.  May be NULL if the Expression doesn't care.
-    //------------------------------------------------------------------
-    virtual ClangExpressionVariableList *
-    LocalVariables () = 0;
-    
-    //------------------------------------------------------------------
     /// Return the object that the parser should allow to access ASTs.
     /// May be NULL if the ASTs do not need to be transformed.
     ///

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionParser.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionParser.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionParser.h Thu Apr  4 21:22:57 2013
@@ -84,6 +84,10 @@ public:
     ///     and func_end do not delimit an allocated region; the allocated
     ///     region may begin before func_addr.)
     ///
+    /// @param[in] execution_unit_ap
+    ///     After parsing, ownership of the execution unit for
+    ///     for the expression is handed to this auto_ptr.
+    ///
     /// @param[in] exe_ctx
     ///     The execution context to write the function into.
     ///
@@ -108,6 +112,7 @@ public:
     Error
     PrepareForExecution (lldb::addr_t &func_addr,
                          lldb::addr_t &func_end,
+                         std::auto_ptr<IRExecutionUnit> &execution_unit_ap,
                          ExecutionContext &exe_ctx,
                          bool &evaluated_statically,
                          lldb::ClangExpressionVariableSP &const_result,

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Thu Apr  4 21:22:57 2013
@@ -620,6 +620,7 @@ private:
 	//------------------------------------------------------------------
 
     std::auto_ptr<ClangExpressionParser>    m_parser;               ///< The parser responsible for compiling the function.
+    std::auto_ptr<IRExecutionUnit>          m_execution_unit_ap;
     
     Function                       *m_function_ptr;                 ///< The function we're going to call.  May be NULL if we don't have debug info for the function.
     Address                         m_function_addr;                ///< If we don't have the FunctionSP, we at least need the address & return type.

Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Thu Apr  4 21:22:57 2013
@@ -243,16 +243,6 @@ public:
     }
     
     //------------------------------------------------------------------
-    /// Return the object that the parser should use when registering
-    /// local variables.  May be NULL if the Expression doesn't care.
-    //------------------------------------------------------------------
-    ClangExpressionVariableList *
-    LocalVariables ()
-    {
-        return m_local_variables.get();
-    }
-    
-    //------------------------------------------------------------------
     /// Return the object that the parser should allow to access ASTs.
     /// May be NULL if the ASTs do not need to be transformed.
     ///
@@ -431,7 +421,7 @@ private:
     ResultType                                  m_desired_type;         ///< The type to coerce the expression's result to.  If eResultTypeAny, inferred from the expression.
     
     std::auto_ptr<ClangExpressionDeclMap>       m_expr_decl_map;        ///< The map to use when parsing and materializing the expression.
-    std::auto_ptr<ClangExpressionVariableList>  m_local_variables;      ///< The local expression variables, if the expression is DWARF.
+    std::auto_ptr<IRExecutionUnit>              m_execution_unit_ap;    ///< The execution unit the expression is stored in.
     
     std::auto_ptr<ASTResultSynthesizer>         m_result_synthesizer;   ///< The result synthesizer, if one is needed.
     

Modified: lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUtilityFunction.h Thu Apr  4 21:22:57 2013
@@ -169,6 +169,7 @@ public:
     
 private:
     std::auto_ptr<ClangExpressionDeclMap>   m_expr_decl_map;    ///< The map to use when parsing and materializing the expression.
+    std::auto_ptr<IRExecutionUnit>          m_execution_unit_ap;
     
     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.

Modified: lldb/trunk/include/lldb/Expression/IRExecutionUnit.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRExecutionUnit.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRExecutionUnit.h (original)
+++ lldb/trunk/include/lldb/Expression/IRExecutionUnit.h Thu Apr  4 21:22:57 2013
@@ -26,6 +26,7 @@
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 #include "lldb/Expression/ClangExpression.h"
 #include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/IRMemoryMap.h"
 #include "lldb/Host/Mutex.h"
 
 namespace llvm {
@@ -57,7 +58,7 @@ class Error;
 /// into the target process, the IRExecutionUnit knows how to copy the
 /// emitted code into the target process.
 //----------------------------------------------------------------------
-class IRExecutionUnit 
+class IRExecutionUnit : public IRMemoryMap
 {
 public:
     //------------------------------------------------------------------
@@ -415,47 +416,7 @@ private:
     };
     
     //----------------------------------------------------------------------
-    /// @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
-        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
-
-        std::unique_ptr<DataBufferHeap> m_data;   ///< If non-NULL, a local data buffer containing the written bytes.  Only populated by WriteNow.
-        
-        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 (Log *log);
-    };
-    
-    //----------------------------------------------------------------------
-    /// @class JittedFunction ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
+    /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.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
@@ -492,10 +453,44 @@ private:
         {
         }
     };
+    
+    static const unsigned eSectionIDInvalid = (unsigned)-1;
+    
+    //----------------------------------------------------------------------
+    /// @class AllocationRecord IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h"
+    /// @brief Enacpsulates a single allocation request made by the JIT.
+    ///
+    /// Allocations made by the JIT are first queued up and then applied in
+    /// bulk to the underlying process.
+    //----------------------------------------------------------------------
+    struct AllocationRecord {
+        lldb::addr_t    m_process_address;
+        uintptr_t       m_host_address;
+        uint32_t        m_permissions;
+        size_t          m_size;
+        unsigned        m_alignment;
+        unsigned        m_section_id;
+        
+        AllocationRecord (uintptr_t host_address,
+                          uint32_t permissions,
+                          size_t size,
+                          unsigned alignment,
+                          unsigned section_id = eSectionIDInvalid) :
+            m_process_address(LLDB_INVALID_ADDRESS),
+            m_host_address(host_address),
+            m_permissions(permissions),
+            m_size(size),
+            m_alignment(alignment),
+            m_section_id(section_id)
+        {
+        }
+        
+        void dump (Log *log);
+    };
+    
+    typedef std::vector<AllocationRecord>   RecordVector;
+    RecordVector                            m_records;
 
-    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
@@ -504,7 +499,6 @@ private:
     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;

Added: lldb/trunk/include/lldb/Expression/IRMemoryMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRMemoryMap.h?rev=178832&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRMemoryMap.h (added)
+++ lldb/trunk/include/lldb/Expression/IRMemoryMap.h Thu Apr  4 21:22:57 2013
@@ -0,0 +1,89 @@
+//===-- 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_IRMemoryMap_h_
+#define lldb_IRMemoryMap_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/UserID.h"
+
+#include <map>
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h"
+/// @brief Encapsulates memory that may exist in the process but must
+///     also be available in the host process.
+///
+/// This class encapsulates a group of memory objects that must be readable
+/// or writable from the host process regardless of whether the process
+/// exists.  This allows the IR interpreter as well as JITted code to access
+/// the same memory.
+///
+/// Point queries against this group of memory objects can be made by the
+/// address in the tar at which they reside.  If the inferior does not
+/// exist, allocations still get made-up addresses.  If an inferior appears
+/// at some point, then those addresses need to be re-mapped.
+//----------------------------------------------------------------------
+class IRMemoryMap
+{
+public:
+    IRMemoryMap (lldb::ProcessSP process_sp);
+    ~IRMemoryMap ();
+    
+    enum AllocationPolicy {
+        eAllocationPolicyInvalid        = 0,    ///< It is an error for an allocation to have this policy.
+        eAllocationPolicyHostOnly,              ///< This allocation was created in the host and will never make it into the process.
+                                                ///< It is an error to create other types of allocations while such allocations exist.
+        eAllocationPolicyMirror,                ///< The intent is that this allocation exist both in the host and the process and have
+                                                ///< the same content in both.
+        eAllocationPolicyProcessOnly            ///< The intent is that this allocation exist only in the process.
+    };
+
+    lldb::addr_t Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error);
+    void Free (lldb::addr_t process_address, Error &error);
+    
+    void WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error);
+    void ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error);
+    
+protected:
+    lldb::ProcessWP GetProcessWP ()
+    {
+        return m_process_wp;
+    }
+    
+private:
+    struct Allocation
+    {
+        lldb::addr_t    m_process_alloc;    ///< The (unaligned) base for the remote allocation
+        lldb::addr_t    m_process_start;    ///< The base address of the allocation in the process
+        size_t          m_size;             ///< The size of the requested allocation
+        uint32_t        m_permissions;      ///< The access permissions on the memory in the process.  In the host, the memory is always read/write.
+        uint8_t         m_alignment;        ///< The alignment of the requested allocation
+        
+        std::unique_ptr<DataBufferHeap> m_data;
+        
+        AllocationPolicy    m_policy;
+    };
+    
+    lldb::ProcessWP                             m_process_wp;
+    typedef std::map<lldb::addr_t, Allocation>  AllocationMap;
+    AllocationMap                               m_allocations;
+    
+    lldb::addr_t FindSpace (size_t size);
+    bool ContainsHostOnlyAllocations ();
+    AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size);
+};
+    
+}
+
+#endif

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Thu Apr  4 21:22:57 2013
@@ -118,6 +118,7 @@ class   InlineFunctionInfo;
 class   InputReader;
 class   Instruction;
 class   InstructionList;
+class   IRExecutionUnit;
 class   LanguageRuntime;
 class   LineTable;
 class   Listener;

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Apr  4 21:22:57 2013
@@ -497,6 +497,7 @@
 		49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268ED0A4140FF54200DE830F /* DataEncoder.cpp */; };
 		49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; };
 		49DA65031485C92A005FF180 /* AppleObjCTypeVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCTypeVendor.cpp */; };
+		49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; };
 		4C6649A014EEE7F100B0316F /* StreamCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C66499F14EEE7F100B0316F /* StreamCallback.h */; };
 		4C6649A314EEE81000B0316F /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6649A214EEE81000B0316F /* StreamCallback.cpp */; };
 		4C701C1E15ABB70C00B50001 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26D55234159A7DB100708D8D /* libxml2.dylib */; };
@@ -1449,6 +1450,7 @@
 		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>"; };
+		49C66B1C17011A43004D1922 /* IRMemoryMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IRMemoryMap.h; path = include/lldb/Expression/IRMemoryMap.h; 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>"; };
@@ -1459,6 +1461,7 @@
 		49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = "<group>"; };
 		49DA65021485C92A005FF180 /* AppleObjCTypeVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCTypeVendor.cpp; sourceTree = "<group>"; };
 		49DA65041485C942005FF180 /* AppleObjCTypeVendor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCTypeVendor.h; sourceTree = "<group>"; };
+		49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRMemoryMap.cpp; path = source/Expression/IRMemoryMap.cpp; sourceTree = "<group>"; };
 		49E45FA911F660DC008F7B28 /* ClangASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTType.h; path = include/lldb/Symbol/ClangASTType.h; sourceTree = "<group>"; };
 		49E45FAD11F660FE008F7B28 /* ClangASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTType.cpp; path = source/Symbol/ClangASTType.cpp; sourceTree = "<group>"; };
 		49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = "<group>"; };
@@ -2892,6 +2895,8 @@
 				491193501226386000578B7F /* ASTStructExtractor.cpp */,
 				49CF9833122C718B007A0B96 /* IRDynamicChecks.h */,
 				49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */,
+				49C66B1C17011A43004D1922 /* IRMemoryMap.h */,
+				49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */,
 				4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */,
 				4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */,
 				49307AB111DEA4F20081F992 /* IRForTarget.h */,
@@ -4298,6 +4303,7 @@
 				260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */,
 				260CC64B15D0440D002BF2E0 /* OptionValueProperties.cpp in Sources */,
 				260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */,
+				49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */,
 				260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */,
 				260CC64E15D0440D002BF2E0 /* OptionValueFileSpec.cpp in Sources */,
 				260CC64F15D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp in Sources */,

Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Thu Apr  4 21:22:57 2013
@@ -461,7 +461,8 @@ static bool FindFunctionInModule (ConstS
 
 Error
 ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, 
-                                            lldb::addr_t &func_end, 
+                                            lldb::addr_t &func_end,
+                                            std::auto_ptr<IRExecutionUnit> &execution_unit_ap,
                                             ExecutionContext &exe_ctx,
                                             bool &evaluated_statically,
                                             lldb::ClangExpressionVariableSP &const_result,
@@ -593,6 +594,8 @@ ClangExpressionParser::PrepareForExecuti
     }
     
     m_execution_unit->GetRunnableInfo(err, func_addr, func_end);
+    
+    execution_unit_ap = m_execution_unit;
         
     return err;
 }

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Thu Apr  4 21:22:57 2013
@@ -266,6 +266,7 @@ ClangFunction::WriteFunctionWrapper (Exe
     
     Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
                                                     m_jit_end_addr,
+                                                    m_execution_unit_ap,
                                                     exe_ctx, 
                                                     evaluated_statically,
                                                     const_result,

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Thu Apr  4 21:22:57 2013
@@ -463,6 +463,7 @@ ClangUserExpression::Parse (Stream &erro
             
     Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
                                                   m_jit_end_addr,
+                                                  m_execution_unit_ap,
                                                   exe_ctx,
                                                   m_evaluated_statically,
                                                   m_const_result,

Modified: lldb/trunk/source/Expression/ClangUtilityFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUtilityFunction.cpp?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUtilityFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangUtilityFunction.cpp Thu Apr  4 21:22:57 2013
@@ -130,7 +130,8 @@ ClangUtilityFunction::Install (Stream &e
     bool evaluated_statically = false; // should stay that way
     
     Error jit_error = parser.PrepareForExecution (m_jit_start_addr, 
-                                                  m_jit_end_addr, 
+                                                  m_jit_end_addr,
+                                                  m_execution_unit_ap,
                                                   exe_ctx,
                                                   evaluated_statically,
                                                   const_result,

Modified: lldb/trunk/source/Expression/IRExecutionUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRExecutionUnit.cpp?rev=178832&r1=178831&r2=178832&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRExecutionUnit.cpp (original)
+++ lldb/trunk/source/Expression/IRExecutionUnit.cpp Thu Apr  4 21:22:57 2013
@@ -1,4 +1,4 @@
-//===-- IRExecutionUnit.cpp ------------------------------*- C++ -*-===//
+//===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -29,7 +29,7 @@ IRExecutionUnit::IRExecutionUnit (std::a
                                   ConstString &name,
                                   lldb::ProcessSP process_sp,
                                   std::vector<std::string> &cpu_features) :
-    m_process_wp(process_sp),
+    IRMemoryMap(process_sp),
     m_module_ap(module_ap),
     m_module(m_module_ap.get()),
     m_cpu_features(cpu_features),
@@ -45,89 +45,55 @@ IRExecutionUnit::WriteNow (const uint8_t
                            size_t size,
                            Error &error)
 {    
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
-    auto iter = m_allocations.insert(m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-    
-    allocation.m_size = size;
-    allocation.m_alignment = 8;
-    allocation.m_data.reset(new DataBufferHeap(bytes, size));
-    allocation.m_local_start = (uintptr_t)allocation.m_data->GetBytes();
-    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");
-        return LLDB_INVALID_ADDRESS;
-    }
-    
-    allocation.m_remote_allocation = process_sp->AllocateMemory(allocation_size,
-                                                                (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
-                                                                err);
+    lldb::addr_t allocation_process_addr = Malloc (size,
+                                                   8,
+                                                   lldb::ePermissionsWritable | lldb::ePermissionsReadable,
+                                                   eAllocationPolicyMirror,
+                                                   error);
     
-    if (!err.Success())
+    if (!error.Success())
         return LLDB_INVALID_ADDRESS;
     
-    process_sp->WriteMemory(allocation.m_remote_allocation, bytes, size, err);
+    WriteMemory(allocation_process_addr, bytes, size, error);
     
-    if (!err.Success())
+    if (!error.Success())
     {
-        process_sp->DeallocateMemory(allocation.m_remote_allocation);
-        allocation.m_remote_allocation = LLDB_INVALID_ADDRESS;
+        Error err;
+        Free (allocation_process_addr, err);
+        
         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)
+    if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
     {
-        log->Printf("IRExecutionUnit::WriteNow() wrote to 0x%llx", allocation.m_remote_start);
-        allocation.dump(log);
-    }
+        DataBufferHeap my_buffer(size, 0);
+        Error err;
+        ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
         
-    return allocation.m_remote_start;
+        if (err.Success())
+        {
+            DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
+
+            StreamString ss;
+            
+            my_extractor.Dump(&ss, 0, lldb::eFormatBytesWithASCII, 1, my_buffer.GetByteSize(), 32, allocation_process_addr, 0, 0);
+            
+            log->PutCString(ss.GetData());
+        }
+    }
+    
+    return allocation_process_addr;
 }
 
 void
 IRExecutionUnit::FreeNow (lldb::addr_t allocation)
 {
-    Log *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;
+    Error err;
     
-    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;
-        }
-    }
+    Free(allocation, err);
 }
 
 Error
@@ -271,7 +237,7 @@ IRExecutionUnit::GetRunnableInfo(Error &
                                  lldb::addr_t &func_addr,
                                  lldb::addr_t &func_end)
 {
-    lldb::ProcessSP process_sp(m_process_wp.lock());
+    lldb::ProcessSP process_sp(GetProcessWP().lock());
     
     func_addr = LLDB_INVALID_ADDRESS;
     func_end = LLDB_INVALID_ADDRESS;
@@ -289,159 +255,147 @@ IRExecutionUnit::GetRunnableInfo(Error &
         func_end = m_function_end_load_addr;
         
         return;
-    }; // someone else may have gotten the mutex first
+    };
+    
+    m_did_jit = true;
     
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    std::string error_string;
+    
+    if (log)
     {
-        Mutex::Locker jit_mutex_locker(m_jit_mutex);
+        std::string s;
+        llvm::raw_string_ostream oss(s);
         
-        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_module->print(oss, NULL);
         
-        m_did_jit = true;
+        oss.flush();
         
-        Log *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;
+    }
+    
+    m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
+    
+    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);
+    
+    if (!error.Success())
+    {
+        // We got an error through our callback!
+        return;
+    }
+    
+    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);
             
-            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;
+    for (JittedFunction &jitted_function : m_jitted_functions)
+    {
+        jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
         
-        if (triple.isOSBinFormatELF())
-        {
-            relocModel = llvm::Reloc::Static;
-            // This will be small for 32-bit and large for 64-bit.
-            codeModel = llvm::CodeModel::JITDefault;
-        }
-        else
+        if (!jitted_function.m_name.compare(m_name.AsCString()))
         {
-            relocModel = llvm::Reloc::PIC_;
-            codeModel = llvm::CodeModel::Small;
+            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.");
         
-        m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
-        
-        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);
+        StreamString disassembly_stream;
         
-        m_execution_engine_ap.reset(builder.create(target_machine));
+        Error err = DisassembleFunction(disassembly_stream, process_sp);
         
-        if (!m_execution_engine_ap.get())
+        if (!err.Success())
         {
-            error.SetErrorToGenericError();
-            error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
-            return;
+            log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
         }
         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);
-        
-        if (!error.Success())
-        {
-            // We got an error through our callback!
-            return;
-        }
-        
-        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;
+            log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
         }
-        
-        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;
     }
+    
+    func_addr = m_function_load_addr;
+    func_end = m_function_end_load_addr;
+    
+    return;
 }
 
 IRExecutionUnit::~IRExecutionUnit ()
@@ -482,20 +436,16 @@ IRExecutionUnit::MemoryManager::allocate
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
 
     uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
-    
-    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-    
-    allocation.m_size = StubSize;
-    allocation.m_alignment = Alignment;
-    allocation.m_local_start = (uintptr_t)return_value;
+
+    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                  StubSize,
+                                                  Alignment));
 
     if (log)
     {
         log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
                     F, StubSize, Alignment, return_value);
-        allocation.dump(log);
     }
         
     return return_value;
@@ -516,19 +466,15 @@ IRExecutionUnit::MemoryManager::allocate
 
     uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
     
-    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-    
-    allocation.m_size = Size;
-    allocation.m_alignment = Alignment;
-    allocation.m_local_start = (uintptr_t)return_value;
+    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                  Size,
+                                                  Alignment));
     
     if (log)
     {
         log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
                                (uint64_t)Size, Alignment, return_value);
-        allocation.dump(log);
     }
         
     return return_value;
@@ -543,21 +489,16 @@ IRExecutionUnit::MemoryManager::allocate
     
     uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
     
-    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-    
-    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;
+    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable | lldb::ePermissionsExecutable,
+                                                  Size,
+                                                  Alignment,
+                                                  SectionID));
     
     if (log)
     {
         log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
                     (uint64_t)Size, Alignment, SectionID, return_value);
-        allocation.dump(log);
     }
         
     return return_value;
@@ -573,20 +514,15 @@ IRExecutionUnit::MemoryManager::allocate
 
     uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
     
-    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-
-    allocation.m_size = Size;
-    allocation.m_alignment = Alignment;
-    allocation.m_local_start = (uintptr_t)return_value;
-    allocation.m_section_id = SectionID;
-    
+    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                  Size,
+                                                  Alignment,
+                                                  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);
     }
         
     return return_value; 
@@ -600,19 +536,15 @@ IRExecutionUnit::MemoryManager::allocate
 
     uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
     
-    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
-    
-    Allocation &allocation(*iter);
-    
-    allocation.m_size = Size;
-    allocation.m_alignment = Alignment;
-    allocation.m_local_start = (uintptr_t)return_value;
+    m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+                                                  Size,
+                                                  Alignment));
     
     if (log)
     {
         log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
                     (uint64_t)Size, Alignment, return_value);
-        allocation.dump(log);
     }
     
     return return_value;
@@ -649,11 +581,16 @@ IRExecutionUnit::MemoryManager::dealloca
 lldb::addr_t
 IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
 {
-    for (Allocation &allocation : m_allocations)
+    for (AllocationRecord &record : m_records)
     {
-        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);
+        if (local_address >= record.m_host_address &&
+            local_address < record.m_host_address + record.m_size)
+        {
+            if (record.m_process_address == LLDB_INVALID_ADDRESS)
+                return LLDB_INVALID_ADDRESS;
+        }
+        
+        return record.m_process_address + (local_address - record.m_host_address);
     }
 
     return LLDB_INVALID_ADDRESS;
@@ -662,11 +599,16 @@ IRExecutionUnit::GetRemoteAddressForLoca
 IRExecutionUnit::AddrRange
 IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
 {
-    for (Allocation &allocation : m_allocations)
+    for (AllocationRecord &record : m_records)
     {
-        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);
+        if (local_address >= record.m_host_address &&
+            local_address < record.m_host_address + record.m_size)
+        {
+            if (record.m_process_address == LLDB_INVALID_ADDRESS)
+                return AddrRange(0, 0);
+            
+            return AddrRange(record.m_process_address, record.m_size);
+        }
     }
     
     return AddrRange (0, 0);
@@ -675,53 +617,38 @@ IRExecutionUnit::GetRemoteRangeForLocal
 bool
 IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
 {
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
     bool ret = true;
     
-    for (Allocation &allocation : m_allocations)
+    lldb_private::Error err;
+    
+    for (AllocationRecord &record : m_records)
     {
-        if (allocation.m_allocated)
+        if (record.m_process_address != LLDB_INVALID_ADDRESS)
             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);
+        record.m_process_address = Malloc(record.m_size,
+                                          record.m_alignment,
+                                          record.m_permissions,
+                                          eAllocationPolicyProcessOnly,
+                                          err);
         
         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)
+        for (AllocationRecord &record : m_records)
         {
-            if (allocation.m_allocated)
-                process_sp->DeallocateMemory(allocation.m_remote_start);
+            if (record.m_process_address != LLDB_INVALID_ADDRESS)
+            {
+                Free(record.m_process_address, err);
+                record.m_process_address = LLDB_INVALID_ADDRESS;
+            }
         }
     }
     
@@ -731,16 +658,17 @@ IRExecutionUnit::CommitAllocations (lldb
 void
 IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
 {
-    for (Allocation &allocation : m_allocations)
+    for (AllocationRecord &record : m_records)
     {
-        if (!allocation.m_allocated)
+        if (record.m_process_address == LLDB_INVALID_ADDRESS)
             continue;
         
-        if (allocation.m_section_id == Allocation::eSectionIDNone)
+        if (record.m_section_id == eSectionIDInvalid)
             continue;
         
-        engine.mapSectionAddress((void*)allocation.m_local_start, allocation.m_remote_start);
+        engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
     }
+    
     // Trigger re-application of relocations.
     engine.finalizeObject();
 }
@@ -748,45 +676,29 @@ IRExecutionUnit::ReportAllocations (llvm
 bool
 IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
 {
-    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
-    for (Allocation &allocation : m_allocations)
+    for (AllocationRecord &record : m_records)
     {
-        if (!allocation.m_allocated)
+        if (record.m_process_address == LLDB_INVALID_ADDRESS)
             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);
-        }
+
+        WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
     }
     
     return true;
 }
 
 void 
-IRExecutionUnit::Allocation::dump (Log *log)
+IRExecutionUnit::AllocationRecord::dump (Log *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_host_address,
                 (unsigned long long)m_size,
-                (unsigned long long)m_remote_start,
+                (unsigned long long)m_process_address,
                 (unsigned)m_alignment,
                 (unsigned)m_section_id);
 }

Added: lldb/trunk/source/Expression/IRMemoryMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRMemoryMap.cpp?rev=178832&view=auto
==============================================================================
--- lldb/trunk/source/Expression/IRMemoryMap.cpp (added)
+++ lldb/trunk/source/Expression/IRMemoryMap.cpp Thu Apr  4 21:22:57 2013
@@ -0,0 +1,410 @@
+//===-- IRMemoryMap.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/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/IRMemoryMap.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb_private;
+
+IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
+    m_process_wp(process_sp)
+{
+}
+
+IRMemoryMap::~IRMemoryMap ()
+{
+    lldb::ProcessSP process_sp = m_process_wp.lock();
+    
+    if (process_sp)
+    {
+        for (AllocationMap::value_type &allocation : m_allocations)
+        {
+            if (allocation.second.m_policy == eAllocationPolicyMirror ||
+                allocation.second.m_policy == eAllocationPolicyHostOnly)
+                process_sp->DeallocateMemory(allocation.second.m_process_alloc);
+            
+            if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+            {
+                log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
+                            (uint64_t)allocation.second.m_process_start,
+                            (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
+            }
+        }
+    }
+}
+
+lldb::addr_t
+IRMemoryMap::FindSpace (size_t size)
+{
+    // Yup, this is just plain O(n) insertion.  We'll use a range tree if we
+    // start caring.
+    
+    lldb::addr_t remote_address = 0x1000; // skip first page of memory
+    
+    for (AllocationMap::value_type &allocation : m_allocations)
+    {
+        if (remote_address < allocation.second.m_process_start &&
+            remote_address + size <= allocation.second.m_process_start)
+            return remote_address;
+        
+        remote_address = allocation.second.m_process_start = allocation.second.m_size;
+    }
+    
+    if (remote_address + size < remote_address)
+        return LLDB_INVALID_ADDRESS; // massively unlikely
+    
+    return remote_address;
+}
+
+bool
+IRMemoryMap::ContainsHostOnlyAllocations ()
+{
+    for (AllocationMap::value_type &allocation : m_allocations)
+    {
+        if (allocation.second.m_policy == eAllocationPolicyHostOnly)
+            return true;
+    }
+    
+    return false;
+}
+
+IRMemoryMap::AllocationMap::iterator
+IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
+{
+    AllocationMap::iterator iter = m_allocations.lower_bound (addr);
+    
+    if (iter == m_allocations.end())
+        return iter;
+    
+    if (iter->first > addr)
+    {
+        if (iter == m_allocations.begin())
+            return m_allocations.end();
+        iter--;
+    }
+    
+    if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
+        return iter;
+    
+    return m_allocations.end();
+}
+
+lldb::addr_t
+IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
+{
+    lldb::ProcessSP process_sp;
+    lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
+    lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
+    
+    size_t          allocation_size = (size ? size : 1) + alignment - 1;
+    
+    switch (policy)
+    {
+    default:
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't malloc: invalid allocation policy");
+        return LLDB_INVALID_ADDRESS;
+    case eAllocationPolicyHostOnly:
+        allocation_address = FindSpace(allocation_size);
+        if (allocation_address == LLDB_INVALID_ADDRESS)
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't malloc: address space is full");
+            return LLDB_INVALID_ADDRESS;
+        }
+        break;
+    case eAllocationPolicyMirror:
+        if (ContainsHostOnlyAllocations())
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
+            return LLDB_INVALID_ADDRESS;
+        }
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+            if (!error.Success())
+                return LLDB_INVALID_ADDRESS;
+        }
+        else
+        {
+            allocation_address = FindSpace(allocation_size);
+            if (allocation_address == LLDB_INVALID_ADDRESS)
+            {
+                error.SetErrorToGenericError();
+                error.SetErrorString("Couldn't malloc: address space is full");
+                return LLDB_INVALID_ADDRESS;
+            }
+        }
+        break;
+    case eAllocationPolicyProcessOnly:
+        if (ContainsHostOnlyAllocations())
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
+            return LLDB_INVALID_ADDRESS;
+        }
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
+            if (!error.Success())
+                return LLDB_INVALID_ADDRESS;
+        }
+        else
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
+            return LLDB_INVALID_ADDRESS;
+        }
+        break;
+    }
+    
+    
+    lldb::addr_t mask = alignment - 1;
+    aligned_address = (allocation_address + mask) & (~mask);
+
+    Allocation &allocation(m_allocations[aligned_address]);
+    
+    allocation.m_process_alloc = allocation_address;
+    allocation.m_process_start = aligned_address;
+    allocation.m_size = size;
+    allocation.m_permissions = permissions;
+    allocation.m_alignment = alignment;
+    allocation.m_policy = policy;
+    
+    switch (policy)
+    {
+    default:
+        assert (0 && "We cannot reach this!");
+    case eAllocationPolicyHostOnly:
+        allocation.m_data.reset(new DataBufferHeap(size, 0));
+        break;
+    case eAllocationPolicyProcessOnly:
+        break;
+    case eAllocationPolicyMirror:
+        allocation.m_data.reset(new DataBufferHeap(size, 0));
+        break;
+    }
+    
+    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+    {
+        const char * policy_string;
+        
+        switch (policy)
+        {
+        default:
+            policy_string = "<invalid policy>";
+            break;
+        case eAllocationPolicyHostOnly:
+            policy_string = "eAllocationPolicyHostOnly";
+            break;
+        case eAllocationPolicyProcessOnly:
+            policy_string = "eAllocationPolicyProcessOnly";
+            break;
+        case eAllocationPolicyMirror:
+            policy_string = "eAllocationPolicyMirror";
+            break;
+        }
+        
+        log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
+                    (uint64_t)size,
+                    (uint64_t)alignment,
+                    (uint64_t)permissions,
+                    policy_string,
+                    aligned_address);
+    }
+    
+    return aligned_address;
+}
+
+void
+IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
+{
+    AllocationMap::iterator iter = m_allocations.find(process_address);
+    
+    if (iter == m_allocations.end())
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't free: allocation doesn't exist");
+        return;
+    }
+    
+    Allocation &allocation = iter->second;
+        
+    switch (allocation.m_policy)
+    {
+    default:
+    case eAllocationPolicyHostOnly:
+        break;
+    case eAllocationPolicyMirror:
+    case eAllocationPolicyProcessOnly:
+        lldb::ProcessSP process_sp = m_process_wp.lock();
+        if (process_sp)
+            process_sp->DeallocateMemory(allocation.m_process_alloc);
+    }
+    
+    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+    {        
+        log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
+                    (uint64_t)process_address,
+                    iter->second.m_process_start,
+                    iter->second.m_process_start + iter->second.m_size);
+    }
+    
+    m_allocations.erase(iter);
+}
+
+void
+IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
+{
+    AllocationMap::iterator iter = FindAllocation(process_address, size);
+    
+    if (iter == m_allocations.end())
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't write: no allocation contains the target range");
+        return;
+    }
+    
+    Allocation &allocation = iter->second;
+    
+    uint64_t offset = process_address - allocation.m_process_start;
+    
+    lldb::ProcessSP process_sp;
+
+    switch (allocation.m_policy)
+    {
+    default:
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't write: invalid allocation policy");
+        return;
+    case eAllocationPolicyHostOnly:
+        if (!allocation.m_data)
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't write: data buffer is empty");
+            return;
+        }
+        ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
+        break;
+    case eAllocationPolicyMirror:
+        if (!allocation.m_data)
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't write: data buffer is empty");
+            return;
+        }
+        ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            process_sp->WriteMemory(process_address, bytes, size, error);
+            if (!error.Success())
+                return;
+        }
+        break;
+    case eAllocationPolicyProcessOnly:
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            process_sp->WriteMemory(process_address, bytes, size, error);
+            if (!error.Success())
+                return;
+        }
+        break;
+    }
+    
+    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+    {        
+        log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
+                    (uint64_t)process_address,
+                    (uint64_t)bytes,
+                    (uint64_t)size,
+                    (uint64_t)allocation.m_process_start,
+                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
+    }
+}
+
+void
+IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
+{
+    AllocationMap::iterator iter = FindAllocation(process_address, size);
+    
+    if (iter == m_allocations.end())
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't read: no allocation contains the target range");
+        return;
+    }
+    
+    Allocation &allocation = iter->second;
+    
+    uint64_t offset = process_address - allocation.m_process_start;
+    
+    lldb::ProcessSP process_sp;
+    
+    switch (allocation.m_policy)
+    {
+    default:
+        error.SetErrorToGenericError();
+        error.SetErrorString("Couldn't read: invalid allocation policy");
+        return;
+    case eAllocationPolicyHostOnly:
+        if (!allocation.m_data)
+        {
+            error.SetErrorToGenericError();
+            error.SetErrorString("Couldn't read: data buffer is empty");
+            return;
+        }
+        ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
+        break;
+    case eAllocationPolicyMirror:
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            process_sp->ReadMemory(process_address, bytes, size, error);
+            if (!error.Success())
+                return;
+        }
+        else
+        {
+            if (!allocation.m_data)
+            {
+                error.SetErrorToGenericError();
+                error.SetErrorString("Couldn't read: data buffer is empty");
+                return;
+            }
+            ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
+        }
+        break;
+    case eAllocationPolicyProcessOnly:
+        process_sp = m_process_wp.lock();
+        if (process_sp)
+        {
+            process_sp->ReadMemory(process_address, bytes, size, error);
+            if (!error.Success())
+                return;
+        }
+        break;
+    }
+    
+    if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+    {
+        log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
+                    (uint64_t)process_address,
+                    (uint64_t)bytes,
+                    (uint64_t)size,
+                    (uint64_t)allocation.m_process_start,
+                    (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
+    }
+}





More information about the lldb-commits mailing list